2010-12-15 17:38:57 +00:00
|
|
|
//===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-12-15 17:38:57 +00:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
//
|
|
|
|
// This file implements semantic analysis for C++0x variadic templates.
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
2014-01-07 11:51:46 +00:00
|
|
|
#include "TypeLocBuilder.h"
|
2024-11-15 08:04:08 +01:00
|
|
|
#include "clang/AST/DynamicRecursiveASTVisitor.h"
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/AST/Expr.h"
|
2024-11-15 08:04:08 +01:00
|
|
|
#include "clang/AST/ExprObjC.h"
|
2012-12-04 09:13:33 +00:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2011-01-04 17:33:58 +00:00
|
|
|
#include "clang/Sema/Lookup.h"
|
2010-12-20 02:24:11 +00:00
|
|
|
#include "clang/Sema/ParsedTemplate.h"
|
2012-07-25 03:56:55 +00:00
|
|
|
#include "clang/Sema/ScopeInfo.h"
|
2024-11-15 08:04:08 +01:00
|
|
|
#include "clang/Sema/Sema.h"
|
2010-12-15 17:38:57 +00:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2010-12-20 22:05:00 +00:00
|
|
|
#include "clang/Sema/Template.h"
|
2024-10-11 20:03:43 +02:00
|
|
|
#include "llvm/Support/SaveAndRestore.h"
|
2023-01-14 11:07:21 -08:00
|
|
|
#include <optional>
|
2010-12-15 17:38:57 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Visitor that collects unexpanded parameter packs
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace {
|
2018-05-09 01:00:01 +00:00
|
|
|
/// A class that collects unexpanded parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
class CollectUnexpandedParameterPacksVisitor
|
|
|
|
: public DynamicRecursiveASTVisitor {
|
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded;
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
bool InLambdaOrBlock = false;
|
|
|
|
unsigned DepthLimit = (unsigned)-1;
|
2017-08-15 19:11:21 +00:00
|
|
|
|
2024-09-09 15:09:43 +08:00
|
|
|
#ifndef NDEBUG
|
2024-10-22 16:51:43 +08:00
|
|
|
bool ContainsIntermediatePacks = false;
|
2024-09-09 15:09:43 +08:00
|
|
|
#endif
|
|
|
|
|
2017-08-15 19:11:21 +00:00
|
|
|
void addUnexpanded(NamedDecl *ND, SourceLocation Loc = SourceLocation()) {
|
2019-05-21 20:10:50 +00:00
|
|
|
if (auto *VD = dyn_cast<VarDecl>(ND)) {
|
2017-08-15 19:11:21 +00:00
|
|
|
// For now, the only problematic case is a generic lambda's templated
|
|
|
|
// call operator, so we don't need to look for all the other ways we
|
|
|
|
// could have reached a dependent parameter pack.
|
2019-05-21 20:10:50 +00:00
|
|
|
auto *FD = dyn_cast<FunctionDecl>(VD->getDeclContext());
|
2017-08-15 19:11:21 +00:00
|
|
|
auto *FTD = FD ? FD->getDescribedFunctionTemplate() : nullptr;
|
|
|
|
if (FTD && FTD->getTemplateParameters()->getDepth() >= DepthLimit)
|
|
|
|
return;
|
2025-02-18 00:42:24 -08:00
|
|
|
} else if (ND->isTemplateParameterPack() &&
|
|
|
|
getDepthAndIndex(ND).first >= DepthLimit) {
|
2017-08-15 19:11:21 +00:00
|
|
|
return;
|
2025-01-29 12:43:52 -08:00
|
|
|
}
|
2017-08-15 19:11:21 +00:00
|
|
|
|
|
|
|
Unexpanded.push_back({ND, Loc});
|
|
|
|
}
|
2025-01-29 12:43:52 -08:00
|
|
|
|
2017-08-15 19:11:21 +00:00
|
|
|
void addUnexpanded(const TemplateTypeParmType *T,
|
|
|
|
SourceLocation Loc = SourceLocation()) {
|
|
|
|
if (T->getDepth() < DepthLimit)
|
|
|
|
Unexpanded.push_back({T, Loc});
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
public:
|
|
|
|
explicit CollectUnexpandedParameterPacksVisitor(
|
2017-08-15 19:11:21 +00:00
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded)
|
2024-11-15 08:04:08 +01:00
|
|
|
: Unexpanded(Unexpanded) {
|
|
|
|
ShouldWalkTypesOfTypeLocs = false;
|
2017-08-15 19:11:21 +00:00
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
// We need this so we can find e.g. attributes on lambdas.
|
|
|
|
ShouldVisitImplicitCode = true;
|
|
|
|
}
|
2024-05-27 18:17:07 +02:00
|
|
|
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Recording occurrences of (unexpanded) parameter packs.
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Record occurrences of template type parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
if (TL.getTypePtr()->isParameterPack())
|
2017-08-15 19:11:21 +00:00
|
|
|
addUnexpanded(TL.getTypePtr(), TL.getNameLoc());
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Record occurrences of template type parameter packs
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
/// when we don't have proper source-location information for
|
|
|
|
/// them.
|
|
|
|
///
|
|
|
|
/// Ideally, this routine would never be used.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
if (T->isParameterPack())
|
2017-08-15 19:11:21 +00:00
|
|
|
addUnexpanded(T);
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Record occurrences of function and non-type template
|
2010-12-23 23:51:58 +00:00
|
|
|
/// parameter packs in an expression.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool VisitDeclRefExpr(DeclRefExpr *E) override {
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-07 16:43:16 +00:00
|
|
|
if (E->getDecl()->isParameterPack())
|
2017-08-15 19:11:21 +00:00
|
|
|
addUnexpanded(E->getDecl(), E->getLocation());
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-12-23 23:51:58 +00:00
|
|
|
return true;
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Record occurrences of template template parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseTemplateName(TemplateName Template) override {
|
2017-08-15 19:11:21 +00:00
|
|
|
if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
|
|
|
|
Template.getAsTemplateDecl())) {
|
2011-01-05 15:48:55 +00:00
|
|
|
if (TTP->isParameterPack())
|
2017-08-15 19:11:21 +00:00
|
|
|
addUnexpanded(TTP);
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2024-10-22 16:51:43 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
ContainsIntermediatePacks |=
|
|
|
|
(bool)Template.getAsSubstTemplateTemplateParmPack();
|
|
|
|
#endif
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseTemplateName(Template);
|
2011-01-05 15:48:55 +00:00
|
|
|
}
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal into Objective-C container literal
|
2012-03-06 20:05:56 +00:00
|
|
|
/// elements that are pack expansions.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override {
|
2012-03-06 20:05:56 +00:00
|
|
|
if (!E->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) {
|
|
|
|
ObjCDictionaryElement Element = E->getKeyValueElement(I);
|
|
|
|
if (Element.isPackExpansion())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
TraverseStmt(Element.Key);
|
|
|
|
TraverseStmt(Element.Value);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// Pruning the search for unexpanded parameter packs.
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal into statements and expressions that
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
/// do not contain unexpanded parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseStmt(Stmt *S) override {
|
2012-07-25 03:56:55 +00:00
|
|
|
Expr *E = dyn_cast_or_null<Expr>(S);
|
2024-10-11 20:03:43 +02:00
|
|
|
if ((E && E->containsUnexpandedParameterPack()) || InLambdaOrBlock)
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseStmt(S);
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
2012-07-25 03:56:55 +00:00
|
|
|
return true;
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal into types that do not contain
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
/// unexpanded parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseType(QualType T) override {
|
2024-10-11 20:03:43 +02:00
|
|
|
if ((!T.isNull() && T->containsUnexpandedParameterPack()) ||
|
|
|
|
InLambdaOrBlock)
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseType(T);
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal into types with location information
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
/// that do not contain unexpanded parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseTypeLoc(TypeLoc TL) override {
|
2018-07-30 19:24:48 +00:00
|
|
|
if ((!TL.getType().isNull() &&
|
2012-07-25 03:56:55 +00:00
|
|
|
TL.getType()->containsUnexpandedParameterPack()) ||
|
2024-10-11 20:03:43 +02:00
|
|
|
InLambdaOrBlock)
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL);
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of parameter packs.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseDecl(Decl *D) override {
|
2017-08-15 19:11:21 +00:00
|
|
|
// A function parameter pack is a pack expansion, so cannot contain
|
2017-08-15 22:58:45 +00:00
|
|
|
// an unexpanded parameter pack. Likewise for a template parameter
|
|
|
|
// pack that contains any references to other packs.
|
2019-01-07 03:25:59 +00:00
|
|
|
if (D && D->isParameterPack())
|
2017-08-15 19:11:21 +00:00
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseDecl(D);
|
2017-08-15 22:58:45 +00:00
|
|
|
}
|
2010-12-15 21:57:59 +00:00
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of pack-expanded attributes.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseAttr(Attr *A) override {
|
2017-08-15 22:58:45 +00:00
|
|
|
if (A->isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseAttr(A);
|
2017-08-15 22:58:45 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of pack expansion expressions and types.
|
2017-08-15 22:58:45 +00:00
|
|
|
///@{
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraversePackExpansionType(PackExpansionType *T) override {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) override {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool TraversePackExpansionExpr(PackExpansionExpr *E) override {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool TraverseCXXFoldExpr(CXXFoldExpr *E) override { return true; }
|
|
|
|
bool TraversePackIndexingExpr(PackIndexingExpr *E) override {
|
|
|
|
return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr());
|
2024-01-27 10:23:38 +01:00
|
|
|
}
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraversePackIndexingType(PackIndexingType *E) override {
|
|
|
|
return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr());
|
2024-01-27 10:23:38 +01:00
|
|
|
}
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) override {
|
|
|
|
return DynamicRecursiveASTVisitor::TraverseStmt(TL.getIndexExpr());
|
2024-01-27 10:23:38 +01:00
|
|
|
}
|
2017-08-15 22:58:45 +00:00
|
|
|
|
|
|
|
///@}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of using-declaration pack expansion.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool
|
|
|
|
TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) override {
|
2017-08-15 22:58:45 +00:00
|
|
|
if (D->isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingValueDecl(D);
|
2017-08-15 22:58:45 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of using-declaration pack expansion.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseUnresolvedUsingTypenameDecl(
|
|
|
|
UnresolvedUsingTypenameDecl *D) override {
|
2017-08-15 22:58:45 +00:00
|
|
|
if (D->isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingTypenameDecl(D);
|
2010-12-15 21:57:59 +00:00
|
|
|
}
|
2011-01-05 17:40:24 +00:00
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of template argument pack expansions.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseTemplateArgument(const TemplateArgument &Arg) override {
|
2011-01-05 17:40:24 +00:00
|
|
|
if (Arg.isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg);
|
2011-01-05 17:40:24 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of template argument pack expansions.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool
|
|
|
|
TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override {
|
2011-01-05 17:40:24 +00:00
|
|
|
if (ArgLoc.getArgument().isPackExpansion())
|
|
|
|
return true;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(ArgLoc);
|
2011-01-05 17:40:24 +00:00
|
|
|
}
|
2012-07-25 03:56:55 +00:00
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of base specifier pack expansions.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) override {
|
2017-08-15 22:58:45 +00:00
|
|
|
if (Base.isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(Base);
|
2017-08-15 22:58:45 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Suppress traversal of mem-initializer pack expansions.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override {
|
2017-08-15 22:58:45 +00:00
|
|
|
if (Init->isPackExpansion())
|
|
|
|
return true;
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init);
|
2017-08-15 22:58:45 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Note whether we're traversing a lambda containing an unexpanded
|
2012-07-25 03:56:55 +00:00
|
|
|
/// parameter pack. In this case, the unexpanded pack can occur anywhere,
|
|
|
|
/// including all the places where we normally wouldn't look. Within a
|
|
|
|
/// lambda, we don't propagate the 'contains unexpanded parameter pack' bit
|
|
|
|
/// outside an expression.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseLambdaExpr(LambdaExpr *Lambda) override {
|
2012-07-25 03:56:55 +00:00
|
|
|
// The ContainsUnexpandedParameterPack bit on a lambda is always correct,
|
|
|
|
// even if it's contained within another lambda.
|
|
|
|
if (!Lambda->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
|
2024-10-11 20:03:43 +02:00
|
|
|
SaveAndRestore _(InLambdaOrBlock, true);
|
2017-08-15 19:11:21 +00:00
|
|
|
unsigned OldDepthLimit = DepthLimit;
|
2012-07-25 03:56:55 +00:00
|
|
|
|
2017-08-15 19:11:21 +00:00
|
|
|
if (auto *TPL = Lambda->getTemplateParameterList())
|
|
|
|
DepthLimit = TPL->getDepth();
|
2012-07-25 03:56:55 +00:00
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
DynamicRecursiveASTVisitor::TraverseLambdaExpr(Lambda);
|
2012-07-25 03:56:55 +00:00
|
|
|
|
2017-08-15 19:11:21 +00:00
|
|
|
DepthLimit = OldDepthLimit;
|
2012-07-25 03:56:55 +00:00
|
|
|
return true;
|
|
|
|
}
|
2017-08-15 19:11:21 +00:00
|
|
|
|
2024-10-11 20:03:43 +02:00
|
|
|
/// Analogously for blocks.
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseBlockExpr(BlockExpr *Block) override {
|
2024-10-11 20:03:43 +02:00
|
|
|
if (!Block->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
SaveAndRestore _(InLambdaOrBlock, true);
|
2024-11-15 08:04:08 +01:00
|
|
|
DynamicRecursiveASTVisitor::TraverseBlockExpr(Block);
|
2024-10-11 20:03:43 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-08-15 19:11:21 +00:00
|
|
|
/// Suppress traversal within pack expansions in lambda captures.
|
|
|
|
bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C,
|
2024-11-15 08:04:08 +01:00
|
|
|
Expr *Init) override {
|
2017-08-15 19:11:21 +00:00
|
|
|
if (C->isPackExpansion())
|
|
|
|
return true;
|
2017-08-15 22:58:45 +00:00
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
return DynamicRecursiveASTVisitor::TraverseLambdaCapture(Lambda, C, Init);
|
2017-08-15 19:11:21 +00:00
|
|
|
}
|
2024-09-09 15:09:43 +08:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2024-11-15 08:04:08 +01:00
|
|
|
bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) override {
|
2024-10-22 16:51:43 +08:00
|
|
|
ContainsIntermediatePacks = true;
|
2024-09-09 15:09:43 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-10-22 16:51:43 +08:00
|
|
|
bool TraverseSubstNonTypeTemplateParmPackExpr(
|
2024-11-15 08:04:08 +01:00
|
|
|
SubstNonTypeTemplateParmPackExpr *) override {
|
2024-10-22 16:51:43 +08:00
|
|
|
ContainsIntermediatePacks = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
bool VisitSubstTemplateTypeParmPackType(
|
|
|
|
SubstTemplateTypeParmPackType *) override {
|
2024-10-22 16:51:43 +08:00
|
|
|
ContainsIntermediatePacks = true;
|
|
|
|
return true;
|
2024-09-09 15:09:43 +08:00
|
|
|
}
|
2024-10-22 16:51:43 +08:00
|
|
|
|
2024-11-15 08:04:08 +01:00
|
|
|
bool VisitSubstTemplateTypeParmPackTypeLoc(
|
|
|
|
SubstTemplateTypeParmPackTypeLoc) override {
|
2024-10-22 16:51:43 +08:00
|
|
|
ContainsIntermediatePacks = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool containsIntermediatePacks() const { return ContainsIntermediatePacks; }
|
2024-09-09 15:09:43 +08:00
|
|
|
#endif
|
2024-11-15 08:04:08 +01:00
|
|
|
};
|
2015-06-22 23:07:51 +00:00
|
|
|
}
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Determine whether it's possible for an unexpanded parameter pack to
|
2014-08-11 23:30:23 +00:00
|
|
|
/// be valid in this location. This only happens when we're in a declaration
|
|
|
|
/// that is nested within an expression that could be expanded, such as a
|
|
|
|
/// lambda-expression within a function call.
|
|
|
|
///
|
|
|
|
/// This is conservatively correct, but may claim that some unexpanded packs are
|
|
|
|
/// permitted when they are not.
|
|
|
|
bool Sema::isUnexpandedParameterPackPermitted() {
|
|
|
|
for (auto *SI : FunctionScopes)
|
|
|
|
if (isa<sema::LambdaScopeInfo>(SI))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-09 01:00:01 +00:00
|
|
|
/// Diagnose all of the unexpanded parameter packs in the given
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
/// vector.
|
2012-07-25 03:56:55 +00:00
|
|
|
bool
|
2011-10-25 03:44:56 +00:00
|
|
|
Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
|
|
|
|
UnexpandedParameterPackContext UPPC,
|
2012-02-22 09:38:11 +00:00
|
|
|
ArrayRef<UnexpandedParameterPack> Unexpanded) {
|
2011-10-25 03:44:56 +00:00
|
|
|
if (Unexpanded.empty())
|
2012-07-25 03:56:55 +00:00
|
|
|
return false;
|
|
|
|
|
2017-08-15 19:11:21 +00:00
|
|
|
// If we are within a lambda expression and referencing a pack that is not
|
2019-08-26 22:51:28 +00:00
|
|
|
// declared within the lambda itself, that lambda contains an unexpanded
|
2024-10-11 20:03:43 +02:00
|
|
|
// parameter pack, and we are done. Analogously for blocks.
|
2012-07-25 03:56:55 +00:00
|
|
|
// FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it
|
|
|
|
// later.
|
2024-10-11 20:03:43 +02:00
|
|
|
SmallVector<UnexpandedParameterPack, 4> ParamPackReferences;
|
|
|
|
if (sema::CapturingScopeInfo *CSI = getEnclosingLambdaOrBlock()) {
|
2019-08-26 22:51:28 +00:00
|
|
|
for (auto &Pack : Unexpanded) {
|
|
|
|
auto DeclaresThisPack = [&](NamedDecl *LocalPack) {
|
|
|
|
if (auto *TTPT = Pack.first.dyn_cast<const TemplateTypeParmType *>()) {
|
|
|
|
auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack);
|
|
|
|
return TTPD && TTPD->getTypeForDecl() == TTPT;
|
2017-08-15 19:11:21 +00:00
|
|
|
}
|
2024-11-27 09:13:28 -08:00
|
|
|
return declaresSameEntity(cast<NamedDecl *>(Pack.first), LocalPack);
|
2019-08-26 22:51:28 +00:00
|
|
|
};
|
2024-10-11 20:03:43 +02:00
|
|
|
if (llvm::any_of(CSI->LocalPacks, DeclaresThisPack))
|
|
|
|
ParamPackReferences.push_back(Pack);
|
2019-08-26 22:51:28 +00:00
|
|
|
}
|
2017-08-15 19:11:21 +00:00
|
|
|
|
2024-10-11 20:03:43 +02:00
|
|
|
if (ParamPackReferences.empty()) {
|
2019-08-26 22:51:28 +00:00
|
|
|
// Construct in lambda only references packs declared outside the lambda.
|
|
|
|
// That's OK for now, but the lambda itself is considered to contain an
|
|
|
|
// unexpanded pack in this case, which will require expansion outside the
|
|
|
|
// lambda.
|
|
|
|
|
|
|
|
// We do not permit pack expansion that would duplicate a statement
|
|
|
|
// expression, not even within a lambda.
|
|
|
|
// FIXME: We could probably support this for statement expressions that
|
|
|
|
// do not contain labels.
|
|
|
|
// FIXME: This is insufficient to detect this problem; consider
|
|
|
|
// f( ({ bad: 0; }) + pack ... );
|
|
|
|
bool EnclosingStmtExpr = false;
|
|
|
|
for (unsigned N = FunctionScopes.size(); N; --N) {
|
|
|
|
sema::FunctionScopeInfo *Func = FunctionScopes[N-1];
|
2021-10-24 17:35:33 -07:00
|
|
|
if (llvm::any_of(
|
|
|
|
Func->CompoundScopes,
|
2019-08-26 22:51:28 +00:00
|
|
|
[](sema::CompoundScopeInfo &CSI) { return CSI.IsStmtExpr; })) {
|
|
|
|
EnclosingStmtExpr = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Coumpound-statements outside the lambda are OK for now; we'll check
|
|
|
|
// for those when we finish handling the lambda.
|
2024-10-11 20:03:43 +02:00
|
|
|
if (Func == CSI)
|
2019-08-26 22:51:28 +00:00
|
|
|
break;
|
2017-08-15 19:11:21 +00:00
|
|
|
}
|
|
|
|
|
2019-08-26 22:51:28 +00:00
|
|
|
if (!EnclosingStmtExpr) {
|
2024-10-11 20:03:43 +02:00
|
|
|
CSI->ContainsUnexpandedParameterPack = true;
|
2019-08-26 22:51:28 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
2024-10-11 20:03:43 +02:00
|
|
|
Unexpanded = ParamPackReferences;
|
2012-07-25 03:56:55 +00:00
|
|
|
}
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<SourceLocation, 4> Locations;
|
|
|
|
SmallVector<IdentifierInfo *, 4> Names;
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown;
|
|
|
|
|
|
|
|
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
|
2014-05-26 06:22:03 +00:00
|
|
|
IdentifierInfo *Name = nullptr;
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
if (const TemplateTypeParmType *TTP
|
|
|
|
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
|
2011-05-01 01:05:51 +00:00
|
|
|
Name = TTP->getIdentifier();
|
2025-01-29 12:43:52 -08:00
|
|
|
else if (NamedDecl *ND = Unexpanded[I].first.dyn_cast<NamedDecl *>())
|
|
|
|
Name = ND->getIdentifier();
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
2014-11-19 07:49:47 +00:00
|
|
|
if (Name && NamesKnown.insert(Name).second)
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
Names.push_back(Name);
|
|
|
|
|
|
|
|
if (Unexpanded[I].second.isValid())
|
|
|
|
Locations.push_back(Unexpanded[I].second);
|
|
|
|
}
|
|
|
|
|
2020-09-23 18:00:23 -04:00
|
|
|
auto DB = Diag(Loc, diag::err_unexpanded_parameter_pack)
|
|
|
|
<< (int)UPPC << (int)Names.size();
|
2015-03-27 17:23:14 +00:00
|
|
|
for (size_t I = 0, E = std::min(Names.size(), (size_t)2); I != E; ++I)
|
|
|
|
DB << Names[I];
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
|
|
|
|
for (unsigned I = 0, N = Locations.size(); I != N; ++I)
|
|
|
|
DB << SourceRange(Locations[I]);
|
2012-07-25 03:56:55 +00:00
|
|
|
return true;
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
|
2010-12-15 17:38:57 +00:00
|
|
|
TypeSourceInfo *T,
|
|
|
|
UnexpandedParameterPackContext UPPC) {
|
|
|
|
// C++0x [temp.variadic]p5:
|
2018-07-30 19:24:48 +00:00
|
|
|
// An appearance of a name of a parameter pack that is not expanded is
|
2010-12-15 17:38:57 +00:00
|
|
|
// ill-formed.
|
|
|
|
if (!T->getType()->containsUnexpandedParameterPack())
|
|
|
|
return false;
|
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
Introduce a RecursiveASTVisitor subclass that finds all unexpanded
parameter packs within a statement, type, etc. Use this visitor to
provide improved diagnostics for the presence of unexpanded parameter
packs in a full expression, base type, declaration type, etc., by
highlighting the unexpanded parameter packs and providing their names,
e.g.,
test/CXX/temp/temp.decls/temp.variadic/p5.cpp:28:85: error: declaration type
contains unexpanded parameter packs 'VeryInnerTypes',
'OuterTypes', ...
...VeryInnerTypes, OuterTypes>, pair<InnerTypes, OuterTypes> > types;
~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ^
llvm-svn: 121883
2010-12-15 19:43:21 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(
|
|
|
|
T->getTypeLoc());
|
|
|
|
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
|
2012-07-25 03:56:55 +00:00
|
|
|
return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
|
2010-12-15 17:38:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::DiagnoseUnexpandedParameterPack(Expr *E,
|
2010-12-16 00:46:58 +00:00
|
|
|
UnexpandedParameterPackContext UPPC) {
|
2010-12-15 17:38:57 +00:00
|
|
|
// C++0x [temp.variadic]p5:
|
2018-07-30 19:24:48 +00:00
|
|
|
// An appearance of a name of a parameter pack that is not expanded is
|
2010-12-15 17:38:57 +00:00
|
|
|
// ill-formed.
|
|
|
|
if (!E->containsUnexpandedParameterPack())
|
|
|
|
return false;
|
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2024-09-09 15:09:43 +08:00
|
|
|
CollectUnexpandedParameterPacksVisitor Visitor(Unexpanded);
|
|
|
|
Visitor.TraverseStmt(E);
|
2024-10-22 16:51:43 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
// The expression might contain a type/subexpression that has been substituted
|
|
|
|
// but has the expansion held off, e.g. a FunctionParmPackExpr which a larger
|
|
|
|
// CXXFoldExpr would expand. It's only possible when expanding a lambda as a
|
|
|
|
// pattern of a fold expression, so don't fire on an empty result in that
|
|
|
|
// case.
|
|
|
|
bool LambdaReferencingOuterPacks =
|
|
|
|
getEnclosingLambdaOrBlock() && Visitor.containsIntermediatePacks();
|
|
|
|
assert((!Unexpanded.empty() || LambdaReferencingOuterPacks) &&
|
2024-09-09 15:09:43 +08:00
|
|
|
"Unable to find unexpanded parameter packs");
|
2024-10-22 16:51:43 +08:00
|
|
|
#endif
|
2018-08-09 21:08:08 +00:00
|
|
|
return DiagnoseUnexpandedParameterPacks(E->getBeginLoc(), UPPC, Unexpanded);
|
2010-12-15 17:38:57 +00:00
|
|
|
}
|
2010-12-16 00:46:58 +00:00
|
|
|
|
2020-08-07 18:17:24 -07:00
|
|
|
bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) {
|
|
|
|
if (!RE->containsUnexpandedParameterPack())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(RE);
|
|
|
|
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
|
|
|
|
|
|
|
|
// We only care about unexpanded references to the RequiresExpr's own
|
|
|
|
// parameter packs.
|
|
|
|
auto Parms = RE->getLocalParameters();
|
|
|
|
llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end());
|
|
|
|
SmallVector<UnexpandedParameterPack, 2> UnexpandedParms;
|
|
|
|
for (auto Parm : Unexpanded)
|
2023-03-08 12:12:33 -08:00
|
|
|
if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>()))
|
2020-08-07 18:17:24 -07:00
|
|
|
UnexpandedParms.push_back(Parm);
|
|
|
|
if (UnexpandedParms.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return DiagnoseUnexpandedParameterPacks(RE->getBeginLoc(), UPPC_Requirement,
|
|
|
|
UnexpandedParms);
|
|
|
|
}
|
|
|
|
|
2010-12-16 00:46:58 +00:00
|
|
|
bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
|
|
|
|
UnexpandedParameterPackContext UPPC) {
|
|
|
|
// C++0x [temp.variadic]p5:
|
2018-07-30 19:24:48 +00:00
|
|
|
// An appearance of a name of a parameter pack that is not expanded is
|
2010-12-16 00:46:58 +00:00
|
|
|
// ill-formed.
|
2018-07-30 19:24:48 +00:00
|
|
|
if (!SS.getScopeRep() ||
|
2010-12-16 00:46:58 +00:00
|
|
|
!SS.getScopeRep()->containsUnexpandedParameterPack())
|
|
|
|
return false;
|
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2010-12-16 00:46:58 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
|
|
|
.TraverseNestedNameSpecifier(SS.getScopeRep());
|
|
|
|
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
|
2012-07-25 03:56:55 +00:00
|
|
|
return DiagnoseUnexpandedParameterPacks(SS.getRange().getBegin(),
|
|
|
|
UPPC, Unexpanded);
|
2010-12-16 00:46:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
|
|
|
|
UnexpandedParameterPackContext UPPC) {
|
|
|
|
// C++0x [temp.variadic]p5:
|
2018-07-30 19:24:48 +00:00
|
|
|
// An appearance of a name of a parameter pack that is not expanded is
|
2010-12-16 00:46:58 +00:00
|
|
|
// ill-formed.
|
|
|
|
switch (NameInfo.getName().getNameKind()) {
|
|
|
|
case DeclarationName::Identifier:
|
|
|
|
case DeclarationName::ObjCZeroArgSelector:
|
|
|
|
case DeclarationName::ObjCOneArgSelector:
|
|
|
|
case DeclarationName::ObjCMultiArgSelector:
|
|
|
|
case DeclarationName::CXXOperatorName:
|
|
|
|
case DeclarationName::CXXLiteralOperatorName:
|
|
|
|
case DeclarationName::CXXUsingDirective:
|
2017-02-07 01:37:30 +00:00
|
|
|
case DeclarationName::CXXDeductionGuideName:
|
2010-12-16 00:46:58 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
case DeclarationName::CXXConstructorName:
|
|
|
|
case DeclarationName::CXXDestructorName:
|
|
|
|
case DeclarationName::CXXConversionFunctionName:
|
2010-12-16 17:19:19 +00:00
|
|
|
// FIXME: We shouldn't need this null check!
|
2010-12-16 01:40:04 +00:00
|
|
|
if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
|
|
|
|
return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC);
|
|
|
|
|
|
|
|
if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack())
|
2010-12-16 00:46:58 +00:00
|
|
|
return false;
|
2010-12-16 01:40:04 +00:00
|
|
|
|
2010-12-16 00:46:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2010-12-16 00:46:58 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
2010-12-16 01:40:04 +00:00
|
|
|
.TraverseType(NameInfo.getName().getCXXNameType());
|
2010-12-16 00:46:58 +00:00
|
|
|
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
|
2012-07-25 03:56:55 +00:00
|
|
|
return DiagnoseUnexpandedParameterPacks(NameInfo.getLoc(), UPPC, Unexpanded);
|
2010-12-16 00:46:58 +00:00
|
|
|
}
|
2010-12-16 08:48:57 +00:00
|
|
|
|
|
|
|
bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc,
|
|
|
|
TemplateName Template,
|
|
|
|
UnexpandedParameterPackContext UPPC) {
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-12-16 08:48:57 +00:00
|
|
|
if (Template.isNull() || !Template.containsUnexpandedParameterPack())
|
|
|
|
return false;
|
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2010-12-16 08:48:57 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
|
|
|
.TraverseTemplateName(Template);
|
|
|
|
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
|
2012-07-25 03:56:55 +00:00
|
|
|
return DiagnoseUnexpandedParameterPacks(Loc, UPPC, Unexpanded);
|
2010-12-16 08:48:57 +00:00
|
|
|
}
|
|
|
|
|
2011-01-03 20:35:03 +00:00
|
|
|
bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
|
|
|
|
UnexpandedParameterPackContext UPPC) {
|
2018-07-30 19:24:48 +00:00
|
|
|
if (Arg.getArgument().isNull() ||
|
2011-01-03 20:35:03 +00:00
|
|
|
!Arg.getArgument().containsUnexpandedParameterPack())
|
|
|
|
return false;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2011-01-03 20:35:03 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
|
|
|
.TraverseTemplateArgumentLoc(Arg);
|
|
|
|
assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs");
|
2012-07-25 03:56:55 +00:00
|
|
|
return DiagnoseUnexpandedParameterPacks(Arg.getLocation(), UPPC, Unexpanded);
|
2011-01-03 20:35:03 +00:00
|
|
|
}
|
|
|
|
|
2010-12-22 21:19:48 +00:00
|
|
|
void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg,
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
2010-12-22 21:19:48 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
|
|
|
.TraverseTemplateArgument(Arg);
|
|
|
|
}
|
|
|
|
|
2010-12-20 22:05:00 +00:00
|
|
|
void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
2010-12-20 22:05:00 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
|
|
|
.TraverseTemplateArgumentLoc(Arg);
|
|
|
|
}
|
|
|
|
|
2010-12-21 00:52:54 +00:00
|
|
|
void Sema::collectUnexpandedParameterPacks(QualType T,
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
2018-07-30 19:24:48 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
|
|
|
|
}
|
2010-12-21 00:52:54 +00:00
|
|
|
|
2011-01-03 22:36:02 +00:00
|
|
|
void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
|
2011-07-23 10:55:15 +00:00
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
2018-07-30 19:24:48 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
|
2016-12-20 21:35:28 +00:00
|
|
|
}
|
2011-01-03 22:36:02 +00:00
|
|
|
|
2016-12-20 21:35:28 +00:00
|
|
|
void Sema::collectUnexpandedParameterPacks(
|
|
|
|
NestedNameSpecifierLoc NNS,
|
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
2011-10-25 03:44:56 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
2016-12-20 21:35:28 +00:00
|
|
|
.TraverseNestedNameSpecifierLoc(NNS);
|
2011-10-25 03:44:56 +00:00
|
|
|
}
|
|
|
|
|
2016-12-20 21:35:28 +00:00
|
|
|
void Sema::collectUnexpandedParameterPacks(
|
|
|
|
const DeclarationNameInfo &NameInfo,
|
|
|
|
SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
2011-10-25 03:44:56 +00:00
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded)
|
|
|
|
.TraverseDeclarationNameInfo(NameInfo);
|
|
|
|
}
|
|
|
|
|
2024-07-17 07:52:40 +02:00
|
|
|
void Sema::collectUnexpandedParameterPacks(
|
|
|
|
Expr *E, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
|
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E);
|
|
|
|
}
|
2011-10-25 03:44:56 +00:00
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
ParsedTemplateArgument
|
2010-12-20 02:24:11 +00:00
|
|
|
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
|
|
|
|
SourceLocation EllipsisLoc) {
|
|
|
|
if (Arg.isInvalid())
|
|
|
|
return Arg;
|
|
|
|
|
|
|
|
switch (Arg.getKind()) {
|
|
|
|
case ParsedTemplateArgument::Type: {
|
|
|
|
TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ParsedTemplateArgument();
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(),
|
2010-12-20 02:24:11 +00:00
|
|
|
Arg.getLocation());
|
|
|
|
}
|
|
|
|
|
2011-01-03 17:17:50 +00:00
|
|
|
case ParsedTemplateArgument::NonType: {
|
|
|
|
ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc);
|
|
|
|
if (Result.isInvalid())
|
|
|
|
return ParsedTemplateArgument();
|
2018-07-30 19:24:48 +00:00
|
|
|
|
|
|
|
return ParsedTemplateArgument(Arg.getKind(), Result.get(),
|
2011-01-03 17:17:50 +00:00
|
|
|
Arg.getLocation());
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-12-20 02:24:11 +00:00
|
|
|
case ParsedTemplateArgument::Template:
|
2011-01-05 17:40:24 +00:00
|
|
|
if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
|
|
|
|
SourceRange R(Arg.getLocation());
|
|
|
|
if (Arg.getScopeSpec().isValid())
|
|
|
|
R.setBegin(Arg.getScopeSpec().getBeginLoc());
|
|
|
|
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
|
|
|
|
<< R;
|
|
|
|
return ParsedTemplateArgument();
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2011-01-05 17:40:24 +00:00
|
|
|
return Arg.getTemplatePackExpansion(EllipsisLoc);
|
2010-12-20 02:24:11 +00:00
|
|
|
}
|
|
|
|
llvm_unreachable("Unhandled template argument kind?");
|
|
|
|
}
|
|
|
|
|
2018-07-30 19:24:48 +00:00
|
|
|
TypeResult Sema::ActOnPackExpansion(ParsedType Type,
|
2010-12-20 02:24:11 +00:00
|
|
|
SourceLocation EllipsisLoc) {
|
|
|
|
TypeSourceInfo *TSInfo;
|
|
|
|
GetTypeFromParser(Type, &TSInfo);
|
|
|
|
if (!TSInfo)
|
|
|
|
return true;
|
|
|
|
|
2022-12-03 11:13:39 -08:00
|
|
|
TypeSourceInfo *TSResult =
|
|
|
|
CheckPackExpansion(TSInfo, EllipsisLoc, std::nullopt);
|
2010-12-20 22:05:00 +00:00
|
|
|
if (!TSResult)
|
|
|
|
return true;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-12-20 22:05:00 +00:00
|
|
|
return CreateParsedType(TSResult->getType(), TSResult);
|
|
|
|
}
|
|
|
|
|
2025-04-03 14:27:18 -03:00
|
|
|
TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
|
|
|
|
SourceLocation EllipsisLoc,
|
|
|
|
UnsignedOrNone NumExpansions) {
|
2011-01-12 17:07:58 +00:00
|
|
|
// Create the pack expansion type and source-location information.
|
2018-07-30 19:24:48 +00:00
|
|
|
QualType Result = CheckPackExpansion(Pattern->getType(),
|
2011-01-12 17:07:58 +00:00
|
|
|
Pattern->getTypeLoc().getSourceRange(),
|
2011-01-14 17:04:44 +00:00
|
|
|
EllipsisLoc, NumExpansions);
|
2011-01-12 17:07:58 +00:00
|
|
|
if (Result.isNull())
|
2014-05-26 06:22:03 +00:00
|
|
|
return nullptr;
|
2013-06-07 20:31:48 +00:00
|
|
|
|
|
|
|
TypeLocBuilder TLB;
|
|
|
|
TLB.pushFullCopy(Pattern->getTypeLoc());
|
|
|
|
PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result);
|
2010-12-20 02:24:11 +00:00
|
|
|
TL.setEllipsisLoc(EllipsisLoc);
|
2013-06-07 20:31:48 +00:00
|
|
|
|
|
|
|
return TLB.getTypeSourceInfo(Context, Result);
|
2010-12-20 02:24:11 +00:00
|
|
|
}
|
2010-12-21 00:52:54 +00:00
|
|
|
|
2013-02-20 22:23:23 +00:00
|
|
|
QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
|
2011-01-14 17:04:44 +00:00
|
|
|
SourceLocation EllipsisLoc,
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone NumExpansions) {
|
2019-05-21 20:10:50 +00:00
|
|
|
// C++11 [temp.variadic]p5:
|
2011-01-12 17:07:58 +00:00
|
|
|
// The pattern of a pack expansion shall name one or more
|
|
|
|
// parameter packs that are not expanded by a nested pack
|
|
|
|
// expansion.
|
2019-05-21 20:10:50 +00:00
|
|
|
//
|
|
|
|
// A pattern containing a deduced type can't occur "naturally" but arises in
|
|
|
|
// the desugaring of an init-capture pack.
|
|
|
|
if (!Pattern->containsUnexpandedParameterPack() &&
|
|
|
|
!Pattern->getContainedDeducedType()) {
|
2011-01-12 17:07:58 +00:00
|
|
|
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
|
|
|
|
<< PatternRange;
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
2020-07-28 12:09:16 -07:00
|
|
|
return Context.getPackExpansionType(Pattern, NumExpansions,
|
|
|
|
/*ExpectPackInType=*/false);
|
2011-01-12 17:07:58 +00:00
|
|
|
}
|
|
|
|
|
2011-01-03 17:17:50 +00:00
|
|
|
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
|
2022-12-03 11:13:39 -08:00
|
|
|
return CheckPackExpansion(Pattern, EllipsisLoc, std::nullopt);
|
2011-01-14 21:20:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone NumExpansions) {
|
2011-01-03 17:17:50 +00:00
|
|
|
if (!Pattern)
|
|
|
|
return ExprError();
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2011-01-03 17:17:50 +00:00
|
|
|
// C++0x [temp.variadic]p5:
|
|
|
|
// The pattern of a pack expansion shall name one or more
|
|
|
|
// parameter packs that are not expanded by a nested pack
|
|
|
|
// expansion.
|
|
|
|
if (!Pattern->containsUnexpandedParameterPack()) {
|
|
|
|
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
|
|
|
|
<< Pattern->getSourceRange();
|
2019-07-16 10:30:21 +00:00
|
|
|
CorrectDelayedTyposInExpr(Pattern);
|
2011-01-03 17:17:50 +00:00
|
|
|
return ExprError();
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2011-01-03 17:17:50 +00:00
|
|
|
// Create the pack expansion expression and source-location information.
|
2025-04-07 12:30:51 -03:00
|
|
|
return new (Context) PackExpansionExpr(Pattern, EllipsisLoc, NumExpansions);
|
2011-01-03 17:17:50 +00:00
|
|
|
}
|
2010-12-21 00:52:54 +00:00
|
|
|
|
2013-02-20 22:23:23 +00:00
|
|
|
bool Sema::CheckParameterPacksForExpansion(
|
|
|
|
SourceLocation EllipsisLoc, SourceRange PatternRange,
|
|
|
|
ArrayRef<UnexpandedParameterPack> Unexpanded,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand,
|
2025-04-03 14:27:18 -03:00
|
|
|
bool &RetainExpansion, UnsignedOrNone &NumExpansions) {
|
2010-12-21 00:52:54 +00:00
|
|
|
ShouldExpand = true;
|
Work-in-progress implementation of C++0x [temp.arg.explicit]p9, which
allows an argument pack determines via explicit specification of
function template arguments to be extended by further, deduced
arguments. For example:
template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
}
There are a number of FIXMEs in here that indicate places where we
need to implement + test retained expansions, plus a number of other
places in deduction where we need to correctly cope with the
explicitly-specified arguments when deducing an argument
pack. Furthermore, it appears that the RecursiveASTVisitor needs to be
auditied; it's missing some traversals (especially w.r.t. template
arguments) that cause it not to find unexpanded parameter packs when
it should.
The good news, however, is that the tr1::tuple implementation now
works fully, and the tr1::bind example (both from N2080) is actually
working now.
llvm-svn: 123163
2011-01-10 07:32:04 +00:00
|
|
|
RetainExpansion = false;
|
2023-03-08 12:12:33 -08:00
|
|
|
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
|
|
|
|
bool HaveFirstPack = false;
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone NumPartialExpansions = std::nullopt;
|
2023-03-08 12:12:33 -08:00
|
|
|
SourceLocation PartiallySubstitutedPackLoc;
|
2025-01-29 12:43:52 -08:00
|
|
|
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
|
2018-07-19 19:00:37 +00:00
|
|
|
|
2023-03-08 12:12:33 -08:00
|
|
|
for (UnexpandedParameterPack ParmPack : Unexpanded) {
|
2010-12-21 00:52:54 +00:00
|
|
|
// Compute the depth and index for this parameter pack.
|
2023-03-08 12:12:33 -08:00
|
|
|
unsigned Depth = 0, Index = 0;
|
|
|
|
IdentifierInfo *Name;
|
|
|
|
bool IsVarDeclPack = false;
|
2025-02-18 00:42:24 -08:00
|
|
|
FunctionParmPackExpr *BindingPack = nullptr;
|
2023-03-08 12:12:33 -08:00
|
|
|
|
|
|
|
if (const TemplateTypeParmType *TTP =
|
|
|
|
ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
|
|
|
|
Depth = TTP->getDepth();
|
|
|
|
Index = TTP->getIndex();
|
|
|
|
Name = TTP->getIdentifier();
|
|
|
|
} else {
|
2024-11-27 09:13:28 -08:00
|
|
|
NamedDecl *ND = cast<NamedDecl *>(ParmPack.first);
|
2023-03-08 12:12:33 -08:00
|
|
|
if (isa<VarDecl>(ND))
|
|
|
|
IsVarDeclPack = true;
|
2025-01-29 12:43:52 -08:00
|
|
|
else if (isa<BindingDecl>(ND)) {
|
|
|
|
// Find the instantiated BindingDecl and check it for a resolved pack.
|
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
|
|
|
|
CurrentInstantiationScope->findInstantiationOf(ND);
|
|
|
|
Decl *B = cast<Decl *>(*Instantiation);
|
|
|
|
Expr *BindingExpr = cast<BindingDecl>(B)->getBinding();
|
2025-02-18 00:42:24 -08:00
|
|
|
BindingPack = cast_if_present<FunctionParmPackExpr>(BindingExpr);
|
|
|
|
if (!BindingPack) {
|
2025-01-29 12:43:52 -08:00
|
|
|
ShouldExpand = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else
|
2023-03-08 12:12:33 -08:00
|
|
|
std::tie(Depth, Index) = getDepthAndIndex(ND);
|
|
|
|
|
|
|
|
Name = ND->getIdentifier();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the size of this argument pack.
|
2024-12-19 13:12:01 +08:00
|
|
|
unsigned NewPackSize, PendingPackExpansionSize = 0;
|
2023-03-08 12:12:33 -08:00
|
|
|
if (IsVarDeclPack) {
|
|
|
|
// Figure out whether we're instantiating to an argument pack or not.
|
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
|
|
|
|
CurrentInstantiationScope->findInstantiationOf(
|
2024-11-27 09:13:28 -08:00
|
|
|
cast<NamedDecl *>(ParmPack.first));
|
|
|
|
if (isa<DeclArgumentPack *>(*Instantiation)) {
|
2023-03-08 12:12:33 -08:00
|
|
|
// We could expand this function parameter pack.
|
2024-11-27 09:13:28 -08:00
|
|
|
NewPackSize = cast<DeclArgumentPack *>(*Instantiation)->size();
|
2023-03-08 12:12:33 -08:00
|
|
|
} else {
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-07 16:43:16 +00:00
|
|
|
// We can't expand this function parameter pack, so we can't expand
|
|
|
|
// the pack expansion.
|
|
|
|
ShouldExpand = false;
|
|
|
|
continue;
|
|
|
|
}
|
2025-02-18 00:42:24 -08:00
|
|
|
} else if (BindingPack) {
|
|
|
|
NewPackSize = BindingPack->getNumExpansions();
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-07 16:43:16 +00:00
|
|
|
} else {
|
2018-07-30 19:24:48 +00:00
|
|
|
// If we don't have a template argument at this depth/index, then we
|
|
|
|
// cannot expand the pack expansion. Make a note of this, but we still
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-07 16:43:16 +00:00
|
|
|
// want to check any parameter packs we *do* have arguments for.
|
2023-03-08 12:12:33 -08:00
|
|
|
if (Depth >= TemplateArgs.getNumLevels() ||
|
|
|
|
!TemplateArgs.hasTemplateArgument(Depth, Index)) {
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-07 16:43:16 +00:00
|
|
|
ShouldExpand = false;
|
|
|
|
continue;
|
|
|
|
}
|
2023-03-08 12:12:33 -08:00
|
|
|
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-07 16:43:16 +00:00
|
|
|
// Determine the size of the argument pack.
|
2024-12-19 13:12:01 +08:00
|
|
|
ArrayRef<TemplateArgument> Pack =
|
|
|
|
TemplateArgs(Depth, Index).getPackAsArray();
|
|
|
|
NewPackSize = Pack.size();
|
|
|
|
PendingPackExpansionSize =
|
|
|
|
llvm::count_if(Pack, [](const TemplateArgument &TA) {
|
|
|
|
if (!TA.isPackExpansion())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (TA.getKind() == TemplateArgument::Type)
|
|
|
|
return !TA.getAsType()
|
2025-03-06 15:12:20 -08:00
|
|
|
->castAs<PackExpansionType>()
|
2024-12-19 13:12:01 +08:00
|
|
|
->getNumExpansions();
|
|
|
|
|
|
|
|
if (TA.getKind() == TemplateArgument::Expression)
|
|
|
|
return !cast<PackExpansionExpr>(TA.getAsExpr())
|
|
|
|
->getNumExpansions();
|
|
|
|
|
|
|
|
return !TA.getNumTemplateExpansions();
|
|
|
|
});
|
2023-03-08 12:12:33 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// C++0x [temp.arg.explicit]p9:
|
|
|
|
// Template argument deduction can extend the sequence of template
|
|
|
|
// arguments corresponding to a template parameter pack, even when the
|
|
|
|
// sequence contains explicitly specified template arguments.
|
2025-02-18 00:42:24 -08:00
|
|
|
if (!IsVarDeclPack && CurrentInstantiationScope) {
|
2023-03-08 12:12:33 -08:00
|
|
|
if (NamedDecl *PartialPack =
|
|
|
|
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
|
|
|
|
unsigned PartialDepth, PartialIndex;
|
|
|
|
std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
|
|
|
|
if (PartialDepth == Depth && PartialIndex == Index) {
|
2011-01-20 23:15:49 +00:00
|
|
|
RetainExpansion = true;
|
2018-07-19 19:00:37 +00:00
|
|
|
// We don't actually know the new pack size yet.
|
2023-03-08 12:12:33 -08:00
|
|
|
NumPartialExpansions = NewPackSize;
|
|
|
|
PartiallySubstitutedPackLoc = ParmPack.second;
|
2018-07-19 19:00:37 +00:00
|
|
|
continue;
|
|
|
|
}
|
2023-03-08 12:12:33 -08:00
|
|
|
}
|
Work-in-progress implementation of C++0x [temp.arg.explicit]p9, which
allows an argument pack determines via explicit specification of
function template arguments to be extended by further, deduced
arguments. For example:
template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
}
There are a number of FIXMEs in here that indicate places where we
need to implement + test retained expansions, plus a number of other
places in deduction where we need to correctly cope with the
explicitly-specified arguments when deducing an argument
pack. Furthermore, it appears that the RecursiveASTVisitor needs to be
auditied; it's missing some traversals (especially w.r.t. template
arguments) that cause it not to find unexpanded parameter packs when
it should.
The good news, however, is that the tr1::tuple implementation now
works fully, and the tr1::bind example (both from N2080) is actually
working now.
llvm-svn: 123163
2011-01-10 07:32:04 +00:00
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2023-03-08 12:12:33 -08:00
|
|
|
if (!NumExpansions) {
|
2024-12-19 13:12:01 +08:00
|
|
|
// This is the first pack we've seen for which we have an argument.
|
2010-12-21 00:52:54 +00:00
|
|
|
// Record it.
|
2023-03-08 12:12:33 -08:00
|
|
|
NumExpansions = NewPackSize;
|
|
|
|
FirstPack.first = Name;
|
|
|
|
FirstPack.second = ParmPack.second;
|
|
|
|
HaveFirstPack = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NewPackSize != *NumExpansions) {
|
2024-12-19 13:12:01 +08:00
|
|
|
// In some cases, we might be handling packs with unexpanded template
|
|
|
|
// arguments. For example, this can occur when substituting into a type
|
|
|
|
// alias declaration that uses its injected template parameters as
|
|
|
|
// arguments:
|
|
|
|
//
|
|
|
|
// template <class... Outer> struct S {
|
|
|
|
// template <class... Inner> using Alias = S<void(Outer, Inner)...>;
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// Consider an instantiation attempt like 'S<int>::Alias<Pack...>', where
|
|
|
|
// Pack comes from another template parameter. 'S<int>' is first
|
|
|
|
// instantiated, expanding the outer pack 'Outer' to <int>. The alias
|
|
|
|
// declaration is accordingly substituted, leaving the template arguments
|
|
|
|
// as unexpanded
|
|
|
|
// '<Pack...>'.
|
|
|
|
//
|
|
|
|
// Since we have no idea of the size of '<Pack...>' until its expansion,
|
|
|
|
// we shouldn't assume its pack size for validation. However if we are
|
|
|
|
// certain that there are extra arguments beyond unexpanded packs, in
|
|
|
|
// which case the pack size is already larger than the previous expansion,
|
|
|
|
// we can complain that before instantiation.
|
|
|
|
unsigned LeastNewPackSize = NewPackSize - PendingPackExpansionSize;
|
|
|
|
if (PendingPackExpansionSize && LeastNewPackSize <= *NumExpansions) {
|
|
|
|
ShouldExpand = false;
|
|
|
|
continue;
|
|
|
|
}
|
2010-12-21 00:52:54 +00:00
|
|
|
// C++0x [temp.variadic]p5:
|
2018-07-30 19:24:48 +00:00
|
|
|
// All of the parameter packs expanded by a pack expansion shall have
|
2010-12-21 00:52:54 +00:00
|
|
|
// the same number of arguments specified.
|
2023-03-08 12:12:33 -08:00
|
|
|
if (HaveFirstPack)
|
|
|
|
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
|
2024-12-19 13:12:01 +08:00
|
|
|
<< FirstPack.first << Name << *NumExpansions
|
|
|
|
<< (LeastNewPackSize != NewPackSize) << LeastNewPackSize
|
2023-03-08 12:12:33 -08:00
|
|
|
<< SourceRange(FirstPack.second) << SourceRange(ParmPack.second);
|
|
|
|
else
|
|
|
|
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
|
2024-12-19 13:12:01 +08:00
|
|
|
<< Name << *NumExpansions << (LeastNewPackSize != NewPackSize)
|
|
|
|
<< LeastNewPackSize << SourceRange(ParmPack.second);
|
2010-12-21 00:52:54 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 22:18:42 +00:00
|
|
|
|
2018-07-19 19:00:37 +00:00
|
|
|
// If we're performing a partial expansion but we also have a full expansion,
|
|
|
|
// expand to the number of common arguments. For example, given:
|
|
|
|
//
|
|
|
|
// template<typename ...T> struct A {
|
|
|
|
// template<typename ...U> void f(pair<T, U>...);
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// ... a call to 'A<int, int>().f<int>' should expand the pack once and
|
|
|
|
// retain an expansion.
|
2023-03-08 12:12:33 -08:00
|
|
|
if (NumPartialExpansions) {
|
|
|
|
if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
|
2018-07-19 19:00:37 +00:00
|
|
|
NamedDecl *PartialPack =
|
|
|
|
CurrentInstantiationScope->getPartiallySubstitutedPack();
|
|
|
|
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
|
2023-03-08 12:12:33 -08:00
|
|
|
<< PartialPack << *NumPartialExpansions << *NumExpansions
|
|
|
|
<< SourceRange(PartiallySubstitutedPackLoc);
|
2018-07-19 19:00:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
2023-03-08 12:12:33 -08:00
|
|
|
|
|
|
|
NumExpansions = NumPartialExpansions;
|
2018-07-19 19:00:37 +00:00
|
|
|
}
|
|
|
|
|
2010-12-21 00:52:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
2010-12-23 22:44:42 +00:00
|
|
|
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone Sema::getNumArgumentsInExpansionFromUnexpanded(
|
[Clang] Fix Handling of Init Capture with Parameter Packs in LambdaScopeForCallOperatorInstantiationRAII (#100766)
This PR addresses issues related to the handling of `init capture` with
parameter packs in Clang's
`LambdaScopeForCallOperatorInstantiationRAII`.
Previously, `addInstantiatedCapturesToScope` would add `init capture`
containing packs to the scope using the type of the `init capture` to
determine the expanded pack size. However, this approach resulted in a
pack size of 0 because `getType()->containsUnexpandedParameterPack()`
returns `false`. After extensive testing, it appears that the correct
pack size can only be inferred from `getInit`.
But `getInit` may reference parameters and `init capture` from an outer
lambda, as shown in the following example:
```cpp
auto L = [](auto... z) {
return [... w = z](auto... y) {
// ...
};
};
```
To address this, `addInstantiatedCapturesToScope` in
`LambdaScopeForCallOperatorInstantiationRAII` should be called last.
Additionally, `addInstantiatedCapturesToScope` has been modified to only
add `init capture` to the scope. The previous implementation incorrectly
called `MakeInstantiatedLocalArgPack` for other non-init captures
containing packs, resulting in a pack size of 0.
### Impact
This patch affects scenarios where
`LambdaScopeForCallOperatorInstantiationRAII` is passed with
`ShouldAddDeclsFromParentScope = false`, preventing the correct addition
of the current lambda's `init capture` to the scope. There are two main
scenarios for `ShouldAddDeclsFromParentScope = false`:
1. **Constraints**: Sometimes constraints are instantiated in place
rather than delayed. In this case,
`LambdaScopeForCallOperatorInstantiationRAII` does not need to add `init
capture` to the scope.
2. **`noexcept` Expressions**: The expressions inside `noexcept` have
already been transformed, and the packs referenced within have been
expanded. Only `RebuildLambdaInfo` needs to add the expanded captures to
the scope, without requiring `addInstantiatedCapturesToScope` from
`LambdaScopeForCallOperatorInstantiationRAII`.
### Considerations
An alternative approach could involve adding a data structure within the
lambda to record the expanded size of the `init capture` pack. However,
this would increase the lambda's size and require extensive
modifications.
This PR is a prerequisite for implmenting
https://github.com/llvm/llvm-project/issues/61426
2024-08-09 23:13:11 +08:00
|
|
|
llvm::ArrayRef<UnexpandedParameterPack> Unexpanded,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone Result = std::nullopt;
|
2023-03-08 12:12:33 -08:00
|
|
|
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
|
|
|
|
// Compute the depth and index for this parameter pack.
|
|
|
|
unsigned Depth;
|
|
|
|
unsigned Index;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2023-03-08 12:12:33 -08:00
|
|
|
if (const TemplateTypeParmType *TTP =
|
|
|
|
Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
|
|
|
|
Depth = TTP->getDepth();
|
|
|
|
Index = TTP->getIndex();
|
2018-07-30 19:24:48 +00:00
|
|
|
} else {
|
2024-11-27 09:13:28 -08:00
|
|
|
NamedDecl *ND = cast<NamedDecl *>(Unexpanded[I].first);
|
2019-05-21 20:10:50 +00:00
|
|
|
if (isa<VarDecl>(ND)) {
|
2023-03-08 12:12:33 -08:00
|
|
|
// Function parameter pack or init-capture pack.
|
|
|
|
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
|
|
|
|
|
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
|
|
|
|
CurrentInstantiationScope->findInstantiationOf(
|
2024-11-27 09:13:28 -08:00
|
|
|
cast<NamedDecl *>(Unexpanded[I].first));
|
|
|
|
if (isa<Decl *>(*Instantiation))
|
2012-07-18 01:29:05 +00:00
|
|
|
// The pattern refers to an unexpanded pack. We're not ready to expand
|
|
|
|
// this pack yet.
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2023-03-08 12:12:33 -08:00
|
|
|
|
2024-11-27 09:13:28 -08:00
|
|
|
unsigned Size = cast<DeclArgumentPack *>(*Instantiation)->size();
|
2023-03-08 12:12:33 -08:00
|
|
|
assert((!Result || *Result == Size) && "inconsistent pack sizes");
|
|
|
|
Result = Size;
|
|
|
|
continue;
|
2011-01-11 03:14:20 +00:00
|
|
|
}
|
2023-03-08 12:12:33 -08:00
|
|
|
|
|
|
|
std::tie(Depth, Index) = getDepthAndIndex(ND);
|
2011-01-11 03:14:20 +00:00
|
|
|
}
|
2023-03-08 12:12:33 -08:00
|
|
|
if (Depth >= TemplateArgs.getNumLevels() ||
|
|
|
|
!TemplateArgs.hasTemplateArgument(Depth, Index))
|
|
|
|
// The pattern refers to an unknown template argument. We're not ready to
|
|
|
|
// expand this pack yet.
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
// Determine the size of the argument pack.
|
|
|
|
unsigned Size = TemplateArgs(Depth, Index).pack_size();
|
|
|
|
assert((!Result || *Result == Size) && "inconsistent pack sizes");
|
|
|
|
Result = Size;
|
2011-01-11 03:14:20 +00:00
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2012-07-18 01:29:05 +00:00
|
|
|
return Result;
|
2011-01-11 03:14:20 +00:00
|
|
|
}
|
|
|
|
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone Sema::getNumArgumentsInExpansion(
|
[Clang] Fix Handling of Init Capture with Parameter Packs in LambdaScopeForCallOperatorInstantiationRAII (#100766)
This PR addresses issues related to the handling of `init capture` with
parameter packs in Clang's
`LambdaScopeForCallOperatorInstantiationRAII`.
Previously, `addInstantiatedCapturesToScope` would add `init capture`
containing packs to the scope using the type of the `init capture` to
determine the expanded pack size. However, this approach resulted in a
pack size of 0 because `getType()->containsUnexpandedParameterPack()`
returns `false`. After extensive testing, it appears that the correct
pack size can only be inferred from `getInit`.
But `getInit` may reference parameters and `init capture` from an outer
lambda, as shown in the following example:
```cpp
auto L = [](auto... z) {
return [... w = z](auto... y) {
// ...
};
};
```
To address this, `addInstantiatedCapturesToScope` in
`LambdaScopeForCallOperatorInstantiationRAII` should be called last.
Additionally, `addInstantiatedCapturesToScope` has been modified to only
add `init capture` to the scope. The previous implementation incorrectly
called `MakeInstantiatedLocalArgPack` for other non-init captures
containing packs, resulting in a pack size of 0.
### Impact
This patch affects scenarios where
`LambdaScopeForCallOperatorInstantiationRAII` is passed with
`ShouldAddDeclsFromParentScope = false`, preventing the correct addition
of the current lambda's `init capture` to the scope. There are two main
scenarios for `ShouldAddDeclsFromParentScope = false`:
1. **Constraints**: Sometimes constraints are instantiated in place
rather than delayed. In this case,
`LambdaScopeForCallOperatorInstantiationRAII` does not need to add `init
capture` to the scope.
2. **`noexcept` Expressions**: The expressions inside `noexcept` have
already been transformed, and the packs referenced within have been
expanded. Only `RebuildLambdaInfo` needs to add the expanded captures to
the scope, without requiring `addInstantiatedCapturesToScope` from
`LambdaScopeForCallOperatorInstantiationRAII`.
### Considerations
An alternative approach could involve adding a data structure within the
lambda to record the expanded size of the `init capture` pack. However,
this would increase the lambda's size and require extensive
modifications.
This PR is a prerequisite for implmenting
https://github.com/llvm/llvm-project/issues/61426
2024-08-09 23:13:11 +08:00
|
|
|
QualType T, const MultiLevelTemplateArgumentList &TemplateArgs) {
|
|
|
|
QualType Pattern = cast<PackExpansionType>(T)->getPattern();
|
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
|
|
|
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
|
|
|
|
return getNumArgumentsInExpansionFromUnexpanded(Unexpanded, TemplateArgs);
|
|
|
|
}
|
|
|
|
|
2010-12-23 22:44:42 +00:00
|
|
|
bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
|
|
|
|
const DeclSpec &DS = D.getDeclSpec();
|
|
|
|
switch (DS.getTypeSpecType()) {
|
2024-01-27 10:23:38 +01:00
|
|
|
case TST_typename_pack_indexing:
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_typename:
|
[C2x] implement typeof and typeof_unqual
This implements WG14 N2927 and WG14 N2930, which together define the
feature for typeof and typeof_unqual, which get the type of their
argument as either fully qualified or fully unqualified. The argument
to either operator is either a type name or an expression. If given a
type name, the type information is pulled directly from the given name.
If given an expression, the type information is pulled from the
expression. Recursive use of these operators is allowed and has the
expected behavior (the innermost operator is resolved to a type, and
that's used to resolve the next layer of typeof specifier, until a
fully resolved type is determined.
Note, we already supported typeof in GNU mode as a non-conforming
extension and we are *not* exposing typeof_unqual as a non-conforming
extension in that mode, nor are we exposing typeof or typeof_unqual as
a nonconforming extension in other language modes. The GNU variant of
typeof supports a form where the parentheses are elided from the
operator when given an expression (e.g., typeof 0 i = 12;). When in C2x
mode, we do not support this extension.
Differential Revision: https://reviews.llvm.org/D134286
2022-09-28 13:25:58 -04:00
|
|
|
case TST_typeof_unqualType:
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_typeofType:
|
2022-08-22 00:27:10 +00:00
|
|
|
#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case TST_##Trait:
|
|
|
|
#include "clang/Basic/TransformTypeTraits.def"
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_atomic: {
|
2010-12-23 22:44:42 +00:00
|
|
|
QualType T = DS.getRepAsType().get();
|
|
|
|
if (!T.isNull() && T->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
}
|
2018-07-30 19:24:48 +00:00
|
|
|
|
[C2x] implement typeof and typeof_unqual
This implements WG14 N2927 and WG14 N2930, which together define the
feature for typeof and typeof_unqual, which get the type of their
argument as either fully qualified or fully unqualified. The argument
to either operator is either a type name or an expression. If given a
type name, the type information is pulled directly from the given name.
If given an expression, the type information is pulled from the
expression. Recursive use of these operators is allowed and has the
expected behavior (the innermost operator is resolved to a type, and
that's used to resolve the next layer of typeof specifier, until a
fully resolved type is determined.
Note, we already supported typeof in GNU mode as a non-conforming
extension and we are *not* exposing typeof_unqual as a non-conforming
extension in that mode, nor are we exposing typeof or typeof_unqual as
a nonconforming extension in other language modes. The GNU variant of
typeof supports a form where the parentheses are elided from the
operator when given an expression (e.g., typeof 0 i = 12;). When in C2x
mode, we do not support this extension.
Differential Revision: https://reviews.llvm.org/D134286
2022-09-28 13:25:58 -04:00
|
|
|
case TST_typeof_unqualExpr:
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_typeofExpr:
|
|
|
|
case TST_decltype:
|
2021-12-06 12:46:54 -05:00
|
|
|
case TST_bitint:
|
2018-07-30 19:24:48 +00:00
|
|
|
if (DS.getRepAsExpr() &&
|
2010-12-23 22:44:42 +00:00
|
|
|
DS.getRepAsExpr()->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
break;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_unspecified:
|
|
|
|
case TST_void:
|
|
|
|
case TST_char:
|
|
|
|
case TST_wchar:
|
2018-05-01 05:02:45 +00:00
|
|
|
case TST_char8:
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_char16:
|
|
|
|
case TST_char32:
|
|
|
|
case TST_int:
|
|
|
|
case TST_int128:
|
|
|
|
case TST_half:
|
|
|
|
case TST_float:
|
|
|
|
case TST_double:
|
2018-06-04 16:07:52 +00:00
|
|
|
case TST_Accum:
|
2018-06-14 14:53:51 +00:00
|
|
|
case TST_Fract:
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_Float16:
|
|
|
|
case TST_float128:
|
2021-09-06 17:49:23 +08:00
|
|
|
case TST_ibm128:
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_bool:
|
|
|
|
case TST_decimal32:
|
|
|
|
case TST_decimal64:
|
|
|
|
case TST_decimal128:
|
|
|
|
case TST_enum:
|
|
|
|
case TST_union:
|
|
|
|
case TST_struct:
|
|
|
|
case TST_interface:
|
|
|
|
case TST_class:
|
|
|
|
case TST_auto:
|
|
|
|
case TST_auto_type:
|
|
|
|
case TST_decltype_auto:
|
[ARM] Add __bf16 as new Bfloat16 C Type
Summary:
This patch upstreams support for a new storage only bfloat16 C type.
This type is used to implement primitive support for bfloat16 data, in
line with the Bfloat16 extension of the Armv8.6-a architecture, as
detailed here:
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a
The bfloat type, and its properties are specified in the Arm Architecture
Reference Manual:
https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
In detail this patch:
- introduces an opaque, storage-only C-type __bf16, which introduces a new bfloat IR type.
This is part of a patch series, starting with command-line and Bfloat16
assembly support. The subsequent patches will upstream intrinsics
support for BFloat16, followed by Matrix Multiplication and the
remaining Virtualization features of the armv8.6-a architecture.
The following people contributed to this patch:
- Luke Cheeseman
- Momchil Velikov
- Alexandros Lamprineas
- Luke Geeson
- Simon Tatham
- Ties Stuij
Reviewers: SjoerdMeijer, rjmccall, rsmith, liutianle, RKSimon, craig.topper, jfb, LukeGeeson, fpetrogalli
Reviewed By: SjoerdMeijer
Subscribers: labrinea, majnemer, asmith, dexonsmith, kristof.beyls, arphaman, danielkiss, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76077
2020-06-05 00:20:02 +01:00
|
|
|
case TST_BFloat16:
|
2018-01-01 18:23:28 +00:00
|
|
|
#define GENERIC_IMAGE_TYPE(ImgType, Id) case TST_##ImgType##_t:
|
2016-04-13 08:33:41 +00:00
|
|
|
#include "clang/Basic/OpenCLImageTypes.def"
|
2024-08-05 10:50:34 -07:00
|
|
|
#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case TST_##Name:
|
|
|
|
#include "clang/Basic/HLSLIntangibleTypes.def"
|
2018-01-01 18:23:28 +00:00
|
|
|
case TST_unknown_anytype:
|
|
|
|
case TST_error:
|
2010-12-23 22:44:42 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-08-29 21:08:16 +00:00
|
|
|
|
2010-12-23 22:44:42 +00:00
|
|
|
for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) {
|
|
|
|
const DeclaratorChunk &Chunk = D.getTypeObject(I);
|
|
|
|
switch (Chunk.Kind) {
|
|
|
|
case DeclaratorChunk::Pointer:
|
|
|
|
case DeclaratorChunk::Reference:
|
|
|
|
case DeclaratorChunk::Paren:
|
2016-01-09 12:53:17 +00:00
|
|
|
case DeclaratorChunk::Pipe:
|
2014-08-29 21:08:16 +00:00
|
|
|
case DeclaratorChunk::BlockPointer:
|
2010-12-23 22:44:42 +00:00
|
|
|
// These declarator chunks cannot contain any parameter packs.
|
|
|
|
break;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2010-12-23 22:44:42 +00:00
|
|
|
case DeclaratorChunk::Array:
|
2014-08-29 21:08:16 +00:00
|
|
|
if (Chunk.Arr.NumElts &&
|
|
|
|
Chunk.Arr.NumElts->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
break;
|
2010-12-23 22:44:42 +00:00
|
|
|
case DeclaratorChunk::Function:
|
2014-08-29 21:08:16 +00:00
|
|
|
for (unsigned i = 0, e = Chunk.Fun.NumParams; i != e; ++i) {
|
|
|
|
ParmVarDecl *Param = cast<ParmVarDecl>(Chunk.Fun.Params[i].Param);
|
|
|
|
QualType ParamTy = Param->getType();
|
|
|
|
assert(!ParamTy.isNull() && "Couldn't parse type?");
|
|
|
|
if (ParamTy->containsUnexpandedParameterPack()) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Chunk.Fun.getExceptionSpecType() == EST_Dynamic) {
|
Store decls in prototypes on the declarator instead of in the AST
This saves two pointers from FunctionDecl that were being used for some
rare and questionable C-only functionality. The DeclsInPrototypeScope
ArrayRef was added in r151712 in order to parse this kind of C code:
enum e {x, y};
int f(enum {y, x} n) {
return x; // should return 1, not 0
}
The challenge is that we parse 'int f(enum {y, x} n)' it its own
function prototype scope that gets popped before we build the
FunctionDecl for 'f'. The original change was doing two questionable
things:
1. Saving all tag decls introduced in prototype scope on a TU-global
Sema variable. This is problematic when you have cases like this, where
'x' and 'y' shouldn't be visible in 'f':
void f(void (*fp)(enum { x, y } e)) { /* no x */ }
This patch fixes that, so now 'f' can't see 'x', which is consistent
with GCC.
2. Storing the decls in FunctionDecl in ActOnFunctionDeclarator so that
they could be used in ActOnStartOfFunctionDef. This is just an
inefficient way to move information around. The AST lives forever, but
the list of non-parameter decls in prototype scope is short lived.
Moving these things to the Declarator solves both of these issues.
Reviewers: rsmith
Subscribers: jmolloy, cfe-commits
Differential Revision: https://reviews.llvm.org/D27279
llvm-svn: 289225
2016-12-09 17:14:05 +00:00
|
|
|
for (unsigned i = 0; i != Chunk.Fun.getNumExceptions(); ++i) {
|
2014-08-29 21:08:16 +00:00
|
|
|
if (Chunk.Fun.Exceptions[i]
|
|
|
|
.Ty.get()
|
|
|
|
->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
}
|
2018-05-03 03:58:32 +00:00
|
|
|
} else if (isComputedNoexcept(Chunk.Fun.getExceptionSpecType()) &&
|
2014-08-29 21:08:16 +00:00
|
|
|
Chunk.Fun.NoexceptExpr->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
|
2014-12-30 02:06:40 +00:00
|
|
|
if (Chunk.Fun.hasTrailingReturnType()) {
|
|
|
|
QualType T = Chunk.Fun.getTrailingReturnType().get();
|
2018-07-20 08:19:20 +00:00
|
|
|
if (!T.isNull() && T->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
2014-12-30 02:06:40 +00:00
|
|
|
}
|
2014-08-29 21:08:16 +00:00
|
|
|
break;
|
|
|
|
|
2010-12-23 22:44:42 +00:00
|
|
|
case DeclaratorChunk::MemberPointer:
|
|
|
|
if (Chunk.Mem.Scope().getScopeRep() &&
|
|
|
|
Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-07-20 08:19:20 +00:00
|
|
|
|
2020-01-09 15:07:51 +02:00
|
|
|
if (Expr *TRC = D.getTrailingRequiresClause())
|
|
|
|
if (TRC->containsUnexpandedParameterPack())
|
|
|
|
return true;
|
2020-02-18 10:48:38 +08:00
|
|
|
|
2010-12-23 22:44:42 +00:00
|
|
|
return false;
|
|
|
|
}
|
2011-01-04 17:33:58 +00:00
|
|
|
|
2012-01-13 23:10:36 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Callback to only accept typo corrections that refer to parameter packs.
|
2019-03-25 17:08:51 +00:00
|
|
|
class ParameterPackValidatorCCC final : public CorrectionCandidateCallback {
|
2012-01-13 23:10:36 +00:00
|
|
|
public:
|
2014-03-12 04:55:44 +00:00
|
|
|
bool ValidateCandidate(const TypoCorrection &candidate) override {
|
2012-01-13 23:10:36 +00:00
|
|
|
NamedDecl *ND = candidate.getCorrectionDecl();
|
|
|
|
return ND && ND->isParameterPack();
|
|
|
|
}
|
2019-03-25 17:08:51 +00:00
|
|
|
|
|
|
|
std::unique_ptr<CorrectionCandidateCallback> clone() override {
|
2019-08-14 23:04:18 +00:00
|
|
|
return std::make_unique<ParameterPackValidatorCCC>(*this);
|
2019-03-25 17:08:51 +00:00
|
|
|
}
|
2012-01-13 23:10:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-22 23:07:51 +00:00
|
|
|
}
|
2012-01-13 23:10:36 +00:00
|
|
|
|
2011-01-04 17:33:58 +00:00
|
|
|
ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S,
|
|
|
|
SourceLocation OpLoc,
|
|
|
|
IdentifierInfo &Name,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
// C++0x [expr.sizeof]p5:
|
|
|
|
// The identifier in a sizeof... expression shall name a parameter pack.
|
|
|
|
LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName);
|
|
|
|
LookupName(R, S);
|
2014-05-26 06:22:03 +00:00
|
|
|
|
|
|
|
NamedDecl *ParameterPack = nullptr;
|
2011-01-04 17:33:58 +00:00
|
|
|
switch (R.getResultKind()) {
|
|
|
|
case LookupResult::Found:
|
|
|
|
ParameterPack = R.getFoundDecl();
|
|
|
|
break;
|
2018-07-30 19:24:48 +00:00
|
|
|
|
2011-01-04 17:33:58 +00:00
|
|
|
case LookupResult::NotFound:
|
2019-03-25 17:08:51 +00:00
|
|
|
case LookupResult::NotFoundInCurrentInstantiation: {
|
|
|
|
ParameterPackValidatorCCC CCC{};
|
2014-10-27 18:07:29 +00:00
|
|
|
if (TypoCorrection Corrected =
|
|
|
|
CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr,
|
2019-03-25 17:08:51 +00:00
|
|
|
CCC, CTK_ErrorRecovery)) {
|
2013-08-17 00:46:16 +00:00
|
|
|
diagnoseTypo(Corrected,
|
|
|
|
PDiag(diag::err_sizeof_pack_no_pack_name_suggest) << &Name,
|
|
|
|
PDiag(diag::note_parameter_pack_here));
|
2012-01-13 23:10:36 +00:00
|
|
|
ParameterPack = Corrected.getCorrectionDecl();
|
2011-01-04 17:33:58 +00:00
|
|
|
}
|
Fix clang -Wimplicit-fallthrough warnings across llvm, NFC
This patch should not introduce any behavior changes. It consists of
mostly one of two changes:
1. Replacing fall through comments with the LLVM_FALLTHROUGH macro
2. Inserting 'break' before falling through into a case block consisting
of only 'break'.
We were already using this warning with GCC, but its warning behaves
slightly differently. In this patch, the following differences are
relevant:
1. GCC recognizes comments that say "fall through" as annotations, clang
doesn't
2. GCC doesn't warn on "case N: foo(); default: break;", clang does
3. GCC doesn't warn when the case contains a switch, but falls through
the outer case.
I will enable the warning separately in a follow-up patch so that it can
be cleanly reverted if necessary.
Reviewers: alexfh, rsmith, lattner, rtrieu, EricWF, bollu
Differential Revision: https://reviews.llvm.org/D53950
llvm-svn: 345882
2018-11-01 19:54:45 +00:00
|
|
|
break;
|
2019-03-25 17:08:51 +00:00
|
|
|
}
|
2011-01-04 17:33:58 +00:00
|
|
|
case LookupResult::FoundOverloaded:
|
|
|
|
case LookupResult::FoundUnresolvedValue:
|
|
|
|
break;
|
2018-07-20 08:19:20 +00:00
|
|
|
|
2011-01-04 17:33:58 +00:00
|
|
|
case LookupResult::Ambiguous:
|
|
|
|
DiagnoseAmbiguousLookup(R);
|
|
|
|
return ExprError();
|
|
|
|
}
|
2018-07-20 08:19:20 +00:00
|
|
|
|
2011-01-05 21:11:38 +00:00
|
|
|
if (!ParameterPack || !ParameterPack->isParameterPack()) {
|
2024-01-27 10:23:38 +01:00
|
|
|
Diag(NameLoc, diag::err_expected_name_of_pack) << &Name;
|
2011-01-04 17:33:58 +00:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
2013-02-02 00:25:55 +00:00
|
|
|
MarkAnyDeclReferenced(OpLoc, ParameterPack, true);
|
2012-03-01 21:32:56 +00:00
|
|
|
|
2015-09-23 21:41:42 +00:00
|
|
|
return SizeOfPackExpr::Create(Context, OpLoc, ParameterPack, NameLoc,
|
2025-02-18 00:42:24 -08:00
|
|
|
RParenLoc);
|
2011-01-04 17:33:58 +00:00
|
|
|
}
|
2013-06-20 04:11:21 +00:00
|
|
|
|
2024-01-27 10:23:38 +01:00
|
|
|
static bool isParameterPack(Expr *PackExpression) {
|
|
|
|
if (auto *D = dyn_cast<DeclRefExpr>(PackExpression); D) {
|
|
|
|
ValueDecl *VD = D->getDecl();
|
|
|
|
return VD->isParameterPack();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
|
|
|
|
SourceLocation EllipsisLoc,
|
|
|
|
SourceLocation LSquareLoc,
|
|
|
|
Expr *IndexExpr,
|
|
|
|
SourceLocation RSquareLoc) {
|
|
|
|
bool isParameterPack = ::isParameterPack(PackExpression);
|
|
|
|
if (!isParameterPack) {
|
2024-04-21 11:43:51 +02:00
|
|
|
if (!PackExpression->containsErrors()) {
|
|
|
|
CorrectDelayedTyposInExpr(IndexExpr);
|
|
|
|
Diag(PackExpression->getBeginLoc(), diag::err_expected_name_of_pack)
|
|
|
|
<< PackExpression;
|
|
|
|
}
|
2024-01-27 10:23:38 +01:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
ExprResult Res =
|
|
|
|
BuildPackIndexingExpr(PackExpression, EllipsisLoc, IndexExpr, RSquareLoc);
|
|
|
|
if (!Res.isInvalid())
|
|
|
|
Diag(Res.get()->getBeginLoc(), getLangOpts().CPlusPlus26
|
|
|
|
? diag::warn_cxx23_pack_indexing
|
|
|
|
: diag::ext_pack_indexing);
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2024-11-25 16:16:39 +08:00
|
|
|
ExprResult Sema::BuildPackIndexingExpr(Expr *PackExpression,
|
|
|
|
SourceLocation EllipsisLoc,
|
|
|
|
Expr *IndexExpr,
|
|
|
|
SourceLocation RSquareLoc,
|
|
|
|
ArrayRef<Expr *> ExpandedExprs,
|
|
|
|
bool FullySubstituted) {
|
2024-01-27 10:23:38 +01:00
|
|
|
|
|
|
|
std::optional<int64_t> Index;
|
|
|
|
if (!IndexExpr->isInstantiationDependent()) {
|
|
|
|
llvm::APSInt Value(Context.getIntWidth(Context.getSizeType()));
|
|
|
|
|
|
|
|
ExprResult Res = CheckConvertedConstantExpression(
|
|
|
|
IndexExpr, Context.getSizeType(), Value, CCEK_ArrayBound);
|
|
|
|
if (!Res.isUsable())
|
|
|
|
return ExprError();
|
|
|
|
Index = Value.getExtValue();
|
|
|
|
IndexExpr = Res.get();
|
|
|
|
}
|
|
|
|
|
2024-11-25 16:16:39 +08:00
|
|
|
if (Index && FullySubstituted) {
|
|
|
|
if (*Index < 0 || *Index >= int64_t(ExpandedExprs.size())) {
|
2024-01-27 10:23:38 +01:00
|
|
|
Diag(PackExpression->getBeginLoc(), diag::err_pack_index_out_of_bound)
|
|
|
|
<< *Index << PackExpression << ExpandedExprs.size();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PackIndexingExpr::Create(getASTContext(), EllipsisLoc, RSquareLoc,
|
|
|
|
PackExpression, IndexExpr, Index,
|
2024-11-25 16:16:39 +08:00
|
|
|
ExpandedExprs, FullySubstituted);
|
2024-01-27 10:23:38 +01:00
|
|
|
}
|
|
|
|
|
2023-01-14 12:31:01 -08:00
|
|
|
TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern(
|
|
|
|
TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis,
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone &NumExpansions) const {
|
2013-06-20 04:11:21 +00:00
|
|
|
const TemplateArgument &Argument = OrigLoc.getArgument();
|
|
|
|
assert(Argument.isPackExpansion());
|
|
|
|
switch (Argument.getKind()) {
|
|
|
|
case TemplateArgument::Type: {
|
|
|
|
// FIXME: We shouldn't ever have to worry about missing
|
|
|
|
// type-source info!
|
|
|
|
TypeSourceInfo *ExpansionTSInfo = OrigLoc.getTypeSourceInfo();
|
|
|
|
if (!ExpansionTSInfo)
|
|
|
|
ExpansionTSInfo = Context.getTrivialTypeSourceInfo(Argument.getAsType(),
|
|
|
|
Ellipsis);
|
|
|
|
PackExpansionTypeLoc Expansion =
|
|
|
|
ExpansionTSInfo->getTypeLoc().castAs<PackExpansionTypeLoc>();
|
|
|
|
Ellipsis = Expansion.getEllipsisLoc();
|
|
|
|
|
|
|
|
TypeLoc Pattern = Expansion.getPatternLoc();
|
|
|
|
NumExpansions = Expansion.getTypePtr()->getNumExpansions();
|
|
|
|
|
|
|
|
// We need to copy the TypeLoc because TemplateArgumentLocs store a
|
|
|
|
// TypeSourceInfo.
|
|
|
|
// FIXME: Find some way to avoid the copy?
|
|
|
|
TypeLocBuilder TLB;
|
|
|
|
TLB.pushFullCopy(Pattern);
|
|
|
|
TypeSourceInfo *PatternTSInfo =
|
|
|
|
TLB.getTypeSourceInfo(Context, Pattern.getType());
|
|
|
|
return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
|
|
|
|
PatternTSInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateArgument::Expression: {
|
|
|
|
PackExpansionExpr *Expansion
|
|
|
|
= cast<PackExpansionExpr>(Argument.getAsExpr());
|
|
|
|
Expr *Pattern = Expansion->getPattern();
|
|
|
|
Ellipsis = Expansion->getEllipsisLoc();
|
|
|
|
NumExpansions = Expansion->getNumExpansions();
|
2025-04-12 14:26:30 -03:00
|
|
|
return TemplateArgumentLoc(
|
|
|
|
TemplateArgument(Pattern, Argument.isCanonicalExpr()), Pattern);
|
2013-06-20 04:11:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case TemplateArgument::TemplateExpansion:
|
|
|
|
Ellipsis = OrigLoc.getTemplateEllipsisLoc();
|
|
|
|
NumExpansions = Argument.getNumTemplateExpansions();
|
2020-09-21 13:08:17 +02:00
|
|
|
return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(),
|
2013-06-20 04:11:21 +00:00
|
|
|
OrigLoc.getTemplateQualifierLoc(),
|
|
|
|
OrigLoc.getTemplateNameLoc());
|
|
|
|
|
|
|
|
case TemplateArgument::Declaration:
|
|
|
|
case TemplateArgument::NullPtr:
|
|
|
|
case TemplateArgument::Template:
|
|
|
|
case TemplateArgument::Integral:
|
2024-01-21 23:28:57 +03:00
|
|
|
case TemplateArgument::StructuralValue:
|
2013-06-20 04:11:21 +00:00
|
|
|
case TemplateArgument::Pack:
|
|
|
|
case TemplateArgument::Null:
|
|
|
|
return TemplateArgumentLoc();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("Invalid TemplateArgument Kind!");
|
|
|
|
}
|
2014-11-08 05:07:16 +00:00
|
|
|
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone Sema::getFullyPackExpandedSize(TemplateArgument Arg) {
|
2016-10-19 22:18:42 +00:00
|
|
|
assert(Arg.containsUnexpandedParameterPack());
|
|
|
|
|
|
|
|
// If this is a substituted pack, grab that pack. If not, we don't know
|
|
|
|
// the size yet.
|
|
|
|
// FIXME: We could find a size in more cases by looking for a substituted
|
|
|
|
// pack anywhere within this argument, but that's not necessary in the common
|
|
|
|
// case for 'sizeof...(A)' handling.
|
|
|
|
TemplateArgument Pack;
|
|
|
|
switch (Arg.getKind()) {
|
|
|
|
case TemplateArgument::Type:
|
|
|
|
if (auto *Subst = Arg.getAsType()->getAs<SubstTemplateTypeParmPackType>())
|
|
|
|
Pack = Subst->getArgumentPack();
|
|
|
|
else
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2016-10-19 22:18:42 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateArgument::Expression:
|
|
|
|
if (auto *Subst =
|
|
|
|
dyn_cast<SubstNonTypeTemplateParmPackExpr>(Arg.getAsExpr()))
|
|
|
|
Pack = Subst->getArgumentPack();
|
|
|
|
else if (auto *Subst = dyn_cast<FunctionParmPackExpr>(Arg.getAsExpr())) {
|
2025-02-18 00:42:24 -08:00
|
|
|
for (ValueDecl *PD : *Subst)
|
2016-10-19 22:18:42 +00:00
|
|
|
if (PD->isParameterPack())
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2016-10-19 22:18:42 +00:00
|
|
|
return Subst->getNumExpansions();
|
|
|
|
} else
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2016-10-19 22:18:42 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateArgument::Template:
|
|
|
|
if (SubstTemplateTemplateParmPackStorage *Subst =
|
|
|
|
Arg.getAsTemplate().getAsSubstTemplateTemplateParmPack())
|
|
|
|
Pack = Subst->getArgumentPack();
|
|
|
|
else
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2016-10-19 22:18:42 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TemplateArgument::Declaration:
|
|
|
|
case TemplateArgument::NullPtr:
|
|
|
|
case TemplateArgument::TemplateExpansion:
|
|
|
|
case TemplateArgument::Integral:
|
2024-01-21 23:28:57 +03:00
|
|
|
case TemplateArgument::StructuralValue:
|
2016-10-19 22:18:42 +00:00
|
|
|
case TemplateArgument::Pack:
|
|
|
|
case TemplateArgument::Null:
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2016-10-19 22:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check that no argument in the pack is itself a pack expansion.
|
|
|
|
for (TemplateArgument Elem : Pack.pack_elements()) {
|
|
|
|
// There's no point recursing in this case; we would have already
|
|
|
|
// expanded this pack expansion into the enclosing pack if we could.
|
|
|
|
if (Elem.isPackExpansion())
|
2022-12-03 11:13:39 -08:00
|
|
|
return std::nullopt;
|
2024-04-10 19:23:32 +08:00
|
|
|
// Don't guess the size of unexpanded packs. The pack within a template
|
|
|
|
// argument may have yet to be of a PackExpansion type before we see the
|
|
|
|
// ellipsis in the annotation stage.
|
|
|
|
//
|
|
|
|
// This doesn't mean we would invalidate the optimization: Arg can be an
|
|
|
|
// unexpanded pack regardless of Elem's dependence. For instance,
|
|
|
|
// A TemplateArgument that contains either a SubstTemplateTypeParmPackType
|
|
|
|
// or SubstNonTypeTemplateParmPackExpr is always considered Unexpanded, but
|
|
|
|
// the underlying TemplateArgument thereof may not.
|
|
|
|
if (Elem.containsUnexpandedParameterPack())
|
|
|
|
return std::nullopt;
|
2016-10-19 22:18:42 +00:00
|
|
|
}
|
|
|
|
return Pack.pack_size();
|
|
|
|
}
|
|
|
|
|
2014-11-08 05:07:16 +00:00
|
|
|
static void CheckFoldOperand(Sema &S, Expr *E) {
|
|
|
|
if (!E)
|
|
|
|
return;
|
|
|
|
|
|
|
|
E = E->IgnoreImpCasts();
|
2016-10-20 00:55:15 +00:00
|
|
|
auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
|
|
|
|
if ((OCE && OCE->isInfixBinaryOp()) || isa<BinaryOperator>(E) ||
|
|
|
|
isa<AbstractConditionalOperator>(E)) {
|
2014-11-08 05:07:16 +00:00
|
|
|
S.Diag(E->getExprLoc(), diag::err_fold_expression_bad_operand)
|
|
|
|
<< E->getSourceRange()
|
2018-08-09 21:08:08 +00:00
|
|
|
<< FixItHint::CreateInsertion(E->getBeginLoc(), "(")
|
2018-08-09 21:09:38 +00:00
|
|
|
<< FixItHint::CreateInsertion(E->getEndLoc(), ")");
|
2014-11-08 05:07:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-06 15:57:35 -07:00
|
|
|
ExprResult Sema::ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
|
2014-11-08 05:07:16 +00:00
|
|
|
tok::TokenKind Operator,
|
|
|
|
SourceLocation EllipsisLoc, Expr *RHS,
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
// LHS and RHS must be cast-expressions. We allow an arbitrary expression
|
|
|
|
// in the parser and reduce down to just cast-expressions here.
|
|
|
|
CheckFoldOperand(*this, LHS);
|
|
|
|
CheckFoldOperand(*this, RHS);
|
|
|
|
|
2017-02-15 19:57:10 +00:00
|
|
|
auto DiscardOperands = [&] {
|
|
|
|
CorrectDelayedTyposInExpr(LHS);
|
|
|
|
CorrectDelayedTyposInExpr(RHS);
|
|
|
|
};
|
|
|
|
|
2014-11-08 05:07:16 +00:00
|
|
|
// [expr.prim.fold]p3:
|
|
|
|
// In a binary fold, op1 and op2 shall be the same fold-operator, and
|
|
|
|
// either e1 shall contain an unexpanded parameter pack or e2 shall contain
|
|
|
|
// an unexpanded parameter pack, but not both.
|
|
|
|
if (LHS && RHS &&
|
|
|
|
LHS->containsUnexpandedParameterPack() ==
|
|
|
|
RHS->containsUnexpandedParameterPack()) {
|
2017-02-15 19:57:10 +00:00
|
|
|
DiscardOperands();
|
2014-11-08 05:07:16 +00:00
|
|
|
return Diag(EllipsisLoc,
|
|
|
|
LHS->containsUnexpandedParameterPack()
|
|
|
|
? diag::err_fold_expression_packs_both_sides
|
|
|
|
: diag::err_pack_expansion_without_parameter_packs)
|
|
|
|
<< LHS->getSourceRange() << RHS->getSourceRange();
|
|
|
|
}
|
|
|
|
|
|
|
|
// [expr.prim.fold]p2:
|
|
|
|
// In a unary fold, the cast-expression shall contain an unexpanded
|
|
|
|
// parameter pack.
|
|
|
|
if (!LHS || !RHS) {
|
|
|
|
Expr *Pack = LHS ? LHS : RHS;
|
|
|
|
assert(Pack && "fold expression with neither LHS nor RHS");
|
2023-03-15 01:07:55 +08:00
|
|
|
if (!Pack->containsUnexpandedParameterPack()) {
|
|
|
|
DiscardOperands();
|
2014-11-08 05:07:16 +00:00
|
|
|
return Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
|
|
|
|
<< Pack->getSourceRange();
|
2023-03-15 01:07:55 +08:00
|
|
|
}
|
2014-11-08 05:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Operator);
|
2020-08-06 15:57:35 -07:00
|
|
|
|
|
|
|
// Perform first-phase name lookup now.
|
|
|
|
UnresolvedLookupExpr *ULE = nullptr;
|
|
|
|
{
|
|
|
|
UnresolvedSet<16> Functions;
|
|
|
|
LookupBinOp(S, EllipsisLoc, Opc, Functions);
|
|
|
|
if (!Functions.empty()) {
|
|
|
|
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(
|
|
|
|
BinaryOperator::getOverloadedOperator(Opc));
|
|
|
|
ExprResult Callee = CreateUnresolvedLookupExpr(
|
|
|
|
/*NamingClass*/ nullptr, NestedNameSpecifierLoc(),
|
|
|
|
DeclarationNameInfo(OpName, EllipsisLoc), Functions);
|
|
|
|
if (Callee.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
ULE = cast<UnresolvedLookupExpr>(Callee.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return BuildCXXFoldExpr(ULE, LParenLoc, LHS, Opc, EllipsisLoc, RHS, RParenLoc,
|
2022-12-03 11:13:39 -08:00
|
|
|
std::nullopt);
|
2014-11-08 05:07:16 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 15:57:35 -07:00
|
|
|
ExprResult Sema::BuildCXXFoldExpr(UnresolvedLookupExpr *Callee,
|
|
|
|
SourceLocation LParenLoc, Expr *LHS,
|
2014-11-08 05:07:16 +00:00
|
|
|
BinaryOperatorKind Operator,
|
|
|
|
SourceLocation EllipsisLoc, Expr *RHS,
|
2019-05-13 08:31:14 +00:00
|
|
|
SourceLocation RParenLoc,
|
2025-04-03 14:27:18 -03:00
|
|
|
UnsignedOrNone NumExpansions) {
|
2020-08-06 15:57:35 -07:00
|
|
|
return new (Context)
|
|
|
|
CXXFoldExpr(Context.DependentTy, Callee, LParenLoc, LHS, Operator,
|
|
|
|
EllipsisLoc, RHS, RParenLoc, NumExpansions);
|
2014-11-08 05:07:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
|
|
|
|
BinaryOperatorKind Operator) {
|
|
|
|
// [temp.variadic]p9:
|
|
|
|
// If N is zero for a unary fold-expression, the value of the expression is
|
|
|
|
// && -> true
|
|
|
|
// || -> false
|
|
|
|
// , -> void()
|
|
|
|
// if the operator is not listed [above], the instantiation is ill-formed.
|
|
|
|
//
|
|
|
|
// Note that we need to use something like int() here, not merely 0, to
|
|
|
|
// prevent the result from being a null pointer constant.
|
|
|
|
QualType ScalarType;
|
|
|
|
switch (Operator) {
|
|
|
|
case BO_LOr:
|
|
|
|
return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_false);
|
|
|
|
case BO_LAnd:
|
|
|
|
return ActOnCXXBoolLiteral(EllipsisLoc, tok::kw_true);
|
|
|
|
case BO_Comma:
|
|
|
|
ScalarType = Context.VoidTy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return Diag(EllipsisLoc, diag::err_fold_expression_empty)
|
|
|
|
<< BinaryOperator::getOpcodeStr(Operator);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new (Context) CXXScalarValueInitExpr(
|
|
|
|
ScalarType, Context.getTrivialTypeSourceInfo(ScalarType, EllipsisLoc),
|
|
|
|
EllipsisLoc);
|
|
|
|
}
|