2009-02-28 03:31:52 +08:00
|
|
|
//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
|
|
|
|
//
|
2019-01-19 16:50:56 +08: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
|
2009-02-28 03:31:52 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
//
|
|
|
|
// This file implements C++ template instantiation.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
2010-08-26 06:03:47 +08:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2009-08-05 00:50:30 +08:00
|
|
|
#include "TreeTransform.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2013-10-23 14:44:28 +08:00
|
|
|
#include "clang/AST/ASTLambda.h"
|
2016-08-25 05:25:37 +08:00
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
2018-03-23 08:07:18 +08:00
|
|
|
#include "clang/AST/PrettyDeclStackTrace.h"
|
2020-02-03 21:44:33 +08:00
|
|
|
#include "clang/AST/TypeVisitor.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
Improve behavior in the case of stack exhaustion.
Summary:
Clang performs various recursive operations (such as template instantiation),
and may use non-trivial amounts of stack space in each recursive step (for
instance, due to recursive AST walks). While we try to keep the stack space
used by such steps to a minimum and we have explicit limits on the number of
such steps we perform, it's impractical to guarantee that we won't blow out the
stack on deeply recursive template instantiations on complex ASTs, even with
only a moderately high instantiation depth limit.
The user experience in these cases is generally terrible: we crash with
no hint of what went wrong. Under this patch, we attempt to do better:
* Detect when the stack is nearly exhausted, and produce a warning with a
nice template instantiation backtrace, telling the user that we might
run slowly or crash.
* For cases where we're forced to trigger recursive template
instantiation in arbitrarily-deeply-nested contexts, check whether
we're nearly out of stack space and allocate a new stack (by spawning
a new thread) after producing the warning.
Reviewers: rnk, aaron.ballman
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66361
llvm-svn: 369940
2019-08-27 02:18:07 +08:00
|
|
|
#include "clang/Basic/Stack.h"
|
2010-08-21 02:27:03 +08:00
|
|
|
#include "clang/Sema/DeclSpec.h"
|
2011-06-12 01:19:42 +08:00
|
|
|
#include "clang/Sema/Initialization.h"
|
2010-08-13 04:07:10 +08:00
|
|
|
#include "clang/Sema/Lookup.h"
|
2010-08-24 15:21:54 +08:00
|
|
|
#include "clang/Sema/Template.h"
|
2010-08-25 13:32:35 +08:00
|
|
|
#include "clang/Sema/TemplateDeduction.h"
|
2018-02-10 22:04:45 +08:00
|
|
|
#include "clang/Sema/TemplateInstCallback.h"
|
2020-01-18 15:11:43 +08:00
|
|
|
#include "clang/Sema/SemaConcept.h"
|
2019-03-30 16:42:48 +08:00
|
|
|
#include "llvm/Support/TimeProfiler.h"
|
2009-02-28 03:31:52 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
2010-08-25 13:32:35 +08:00
|
|
|
using namespace sema;
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2009-03-11 02:03:33 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation Support
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Retrieve the template argument list(s) that should be used to
|
2009-08-29 04:31:08 +08:00
|
|
|
/// instantiate the definition of the given declaration.
|
2009-11-10 03:17:50 +08:00
|
|
|
///
|
|
|
|
/// \param D the declaration for which we are computing template instantiation
|
|
|
|
/// arguments.
|
|
|
|
///
|
|
|
|
/// \param Innermost if non-NULL, the innermost template argument list.
|
2010-02-05 15:33:43 +08:00
|
|
|
///
|
|
|
|
/// \param RelativeToPrimary true if we should get the template
|
|
|
|
/// arguments relative to the primary template, even when we're
|
|
|
|
/// dealing with a specialization. This is only relevant for function
|
|
|
|
/// template specializations.
|
2010-05-04 07:29:10 +08:00
|
|
|
///
|
|
|
|
/// \param Pattern If non-NULL, indicates the pattern from which we will be
|
|
|
|
/// instantiating the definition of the given declaration, \p D. This is
|
|
|
|
/// used to determine the proper set of template instantiation arguments for
|
|
|
|
/// friend function template specializations.
|
2009-08-29 01:37:35 +08:00
|
|
|
MultiLevelTemplateArgumentList
|
2018-07-31 03:24:48 +08:00
|
|
|
Sema::getTemplateInstantiationArgs(NamedDecl *D,
|
2010-02-05 15:33:43 +08:00
|
|
|
const TemplateArgumentList *Innermost,
|
2010-05-04 07:29:10 +08:00
|
|
|
bool RelativeToPrimary,
|
|
|
|
const FunctionDecl *Pattern) {
|
2009-08-29 01:37:35 +08:00
|
|
|
// Accumulate the set of template argument lists in this structure.
|
|
|
|
MultiLevelTemplateArgumentList Result;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-10 03:17:50 +08:00
|
|
|
if (Innermost)
|
|
|
|
Result.addOuterTemplateArguments(Innermost);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-08-29 01:37:35 +08:00
|
|
|
DeclContext *Ctx = dyn_cast<DeclContext>(D);
|
2011-05-22 08:21:10 +08:00
|
|
|
if (!Ctx) {
|
2009-08-29 01:37:35 +08:00
|
|
|
Ctx = D->getDeclContext();
|
2013-08-06 09:03:05 +08:00
|
|
|
|
2019-04-26 10:11:23 +08:00
|
|
|
// Add template arguments from a variable template instantiation. For a
|
|
|
|
// class-scope explicit specialization, there are no template arguments
|
|
|
|
// at this level, but there may be enclosing template arguments.
|
|
|
|
VarTemplateSpecializationDecl *Spec =
|
|
|
|
dyn_cast<VarTemplateSpecializationDecl>(D);
|
|
|
|
if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
|
2013-08-06 09:03:05 +08:00
|
|
|
// We're done when we hit an explicit specialization.
|
|
|
|
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
|
|
|
|
!isa<VarTemplatePartialSpecializationDecl>(Spec))
|
|
|
|
return Result;
|
|
|
|
|
|
|
|
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
|
|
|
|
|
|
|
|
// If this variable template specialization was instantiated from a
|
|
|
|
// specialized member that is a variable template, we're done.
|
|
|
|
assert(Spec->getSpecializedTemplate() && "No variable template?");
|
2014-01-17 07:39:20 +08:00
|
|
|
llvm::PointerUnion<VarTemplateDecl*,
|
|
|
|
VarTemplatePartialSpecializationDecl*> Specialized
|
|
|
|
= Spec->getSpecializedTemplateOrPartial();
|
|
|
|
if (VarTemplatePartialSpecializationDecl *Partial =
|
|
|
|
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
|
|
|
|
if (Partial->isMemberSpecialization())
|
|
|
|
return Result;
|
|
|
|
} else {
|
|
|
|
VarTemplateDecl *Tmpl = Specialized.get<VarTemplateDecl *>();
|
|
|
|
if (Tmpl->isMemberSpecialization())
|
|
|
|
return Result;
|
|
|
|
}
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
2011-06-15 22:20:42 +08:00
|
|
|
// If we have a template template parameter with translation unit context,
|
|
|
|
// then we're performing substitution into a default template argument of
|
|
|
|
// this template template parameter before we've constructed the template
|
|
|
|
// that will own this template template parameter. In this case, we
|
|
|
|
// use empty template parameter lists for all of the outer templates
|
|
|
|
// to avoid performing any substitutions.
|
|
|
|
if (Ctx->isTranslationUnit()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
if (TemplateTemplateParmDecl *TTP
|
2011-06-15 22:20:42 +08:00
|
|
|
= dyn_cast<TemplateTemplateParmDecl>(D)) {
|
|
|
|
for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
|
2013-05-17 11:04:50 +08:00
|
|
|
Result.addOuterTemplateArguments(None);
|
2011-06-15 22:20:42 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
}
|
2011-05-22 08:21:10 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-08-29 11:16:09 +08:00
|
|
|
while (!Ctx->isFileContext()) {
|
2009-08-29 01:37:35 +08:00
|
|
|
// Add template arguments from a class template instantiation.
|
2019-04-26 10:11:23 +08:00
|
|
|
ClassTemplateSpecializationDecl *Spec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
|
|
|
|
if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
|
2009-08-29 01:37:35 +08:00
|
|
|
// We're done when we hit an explicit specialization.
|
2010-07-09 02:37:38 +08:00
|
|
|
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
|
|
|
|
!isa<ClassTemplatePartialSpecializationDecl>(Spec))
|
2009-08-29 01:37:35 +08:00
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-29 01:37:35 +08:00
|
|
|
Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
// If this class template specialization was instantiated from a
|
2009-10-14 00:30:37 +08:00
|
|
|
// specialized member that is a class template, we're done.
|
|
|
|
assert(Spec->getSpecializedTemplate() && "No class template?");
|
|
|
|
if (Spec->getSpecializedTemplate()->isMemberSpecialization())
|
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-29 01:37:35 +08:00
|
|
|
// Add template arguments from a function template specialization.
|
2009-08-29 11:16:09 +08:00
|
|
|
else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
|
2010-02-05 15:33:43 +08:00
|
|
|
if (!RelativeToPrimary &&
|
2019-05-02 08:49:14 +08:00
|
|
|
Function->getTemplateSpecializationKindForInstantiation() ==
|
|
|
|
TSK_ExplicitSpecialization)
|
2009-10-14 00:30:37 +08:00
|
|
|
break;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-08-29 01:37:35 +08:00
|
|
|
if (const TemplateArgumentList *TemplateArgs
|
2009-10-14 00:30:37 +08:00
|
|
|
= Function->getTemplateSpecializationArgs()) {
|
|
|
|
// Add the template arguments for this specialization.
|
2009-08-29 01:37:35 +08:00
|
|
|
Result.addOuterTemplateArguments(TemplateArgs);
|
2009-08-29 11:16:09 +08:00
|
|
|
|
2009-10-14 00:30:37 +08:00
|
|
|
// If this function was instantiated from a specialized member that is
|
|
|
|
// a function template, we're done.
|
|
|
|
assert(Function->getPrimaryTemplate() && "No function template?");
|
|
|
|
if (Function->getPrimaryTemplate()->isMemberSpecialization())
|
|
|
|
break;
|
2013-10-23 14:44:28 +08:00
|
|
|
|
|
|
|
// If this function is a generic lambda specialization, we are done.
|
2020-01-09 21:07:51 +08:00
|
|
|
if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function))
|
2013-10-23 14:44:28 +08:00
|
|
|
break;
|
|
|
|
|
2011-03-06 01:54:25 +08:00
|
|
|
} else if (FunctionTemplateDecl *FunTmpl
|
|
|
|
= Function->getDescribedFunctionTemplate()) {
|
|
|
|
// Add the "injected" template arguments.
|
2013-05-17 11:04:50 +08:00
|
|
|
Result.addOuterTemplateArguments(FunTmpl->getInjectedTemplateArgs());
|
2009-10-14 00:30:37 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-08-29 11:16:09 +08:00
|
|
|
// If this is a friend declaration and it declares an entity at
|
|
|
|
// namespace scope, take arguments from its lexical parent
|
2010-05-04 07:29:10 +08:00
|
|
|
// instead of its semantic parent, unless of course the pattern we're
|
|
|
|
// instantiating actually comes from the file's context!
|
2009-08-29 11:16:09 +08:00
|
|
|
if (Function->getFriendObjectKind() &&
|
2010-05-04 07:29:10 +08:00
|
|
|
Function->getDeclContext()->isFileContext() &&
|
|
|
|
(!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
|
2009-08-29 11:16:09 +08:00
|
|
|
Ctx = Function->getLexicalDeclContext();
|
2010-02-05 15:33:43 +08:00
|
|
|
RelativeToPrimary = false;
|
2009-08-29 11:16:09 +08:00
|
|
|
continue;
|
2010-07-09 02:37:38 +08:00
|
|
|
}
|
|
|
|
} else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) {
|
|
|
|
if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
|
|
|
|
QualType T = ClassTemplate->getInjectedClassNameSpecialization();
|
2013-05-17 11:04:50 +08:00
|
|
|
const TemplateSpecializationType *TST =
|
|
|
|
cast<TemplateSpecializationType>(Context.getCanonicalType(T));
|
|
|
|
Result.addOuterTemplateArguments(
|
|
|
|
llvm::makeArrayRef(TST->getArgs(), TST->getNumArgs()));
|
2010-07-09 02:37:38 +08:00
|
|
|
if (ClassTemplate->isMemberSpecialization())
|
|
|
|
break;
|
2009-08-29 11:16:09 +08:00
|
|
|
}
|
2009-08-29 01:37:35 +08:00
|
|
|
}
|
2009-08-29 11:16:09 +08:00
|
|
|
|
|
|
|
Ctx = Ctx->getParent();
|
2010-02-05 15:33:43 +08:00
|
|
|
RelativeToPrimary = false;
|
2009-05-15 07:26:13 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-29 01:37:35 +08:00
|
|
|
return Result;
|
2009-05-15 07:26:13 +08:00
|
|
|
}
|
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
|
2009-11-12 05:54:23 +08:00
|
|
|
switch (Kind) {
|
|
|
|
case TemplateInstantiation:
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
case ExceptionSpecInstantiation:
|
2009-11-12 05:54:23 +08:00
|
|
|
case DefaultTemplateArgumentInstantiation:
|
|
|
|
case DefaultFunctionArgumentInstantiation:
|
|
|
|
case ExplicitTemplateArgumentSubstitution:
|
|
|
|
case DeducedTemplateArgumentSubstitution:
|
|
|
|
case PriorTemplateArgumentSubstitution:
|
2019-10-15 23:24:26 +08:00
|
|
|
case ConstraintsCheck:
|
2020-01-18 15:11:43 +08:00
|
|
|
case NestedRequirementConstraintsCheck:
|
2012-07-08 10:38:24 +08:00
|
|
|
return true;
|
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
case RequirementInstantiation:
|
2009-11-12 05:54:23 +08:00
|
|
|
case DefaultTemplateArgumentChecking:
|
2017-02-24 05:43:43 +08:00
|
|
|
case DeclaringSpecialMember:
|
2019-12-11 08:45:02 +08:00
|
|
|
case DeclaringImplicitEqualityComparison:
|
2017-05-26 06:47:05 +08:00
|
|
|
case DefiningSynthesizedFunction:
|
2018-09-06 06:30:37 +08:00
|
|
|
case ExceptionSpecEvaluation:
|
2019-10-15 23:24:26 +08:00
|
|
|
case ConstraintSubstitution:
|
2019-12-23 14:37:35 +08:00
|
|
|
case ParameterMappingSubstitution:
|
|
|
|
case ConstraintNormalization:
|
2019-10-19 08:04:43 +08:00
|
|
|
case RewritingOperatorAsSpaceship:
|
2009-11-12 05:54:23 +08:00
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-02-10 22:04:45 +08:00
|
|
|
// This function should never be called when Kind's value is Memoization.
|
|
|
|
case Memoization:
|
|
|
|
break;
|
2009-11-12 05:54:23 +08:00
|
|
|
}
|
2012-01-17 14:56:22 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
llvm_unreachable("Invalid SynthesisKind!");
|
2009-11-12 05:54:23 +08:00
|
|
|
}
|
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
2017-02-23 09:43:54 +08:00
|
|
|
Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
|
2014-03-14 04:34:22 +08:00
|
|
|
SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
|
|
|
|
Decl *Entity, NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
|
2015-03-07 00:36:50 +08:00
|
|
|
sema::TemplateDeductionInfo *DeductionInfo)
|
2017-02-24 05:43:43 +08:00
|
|
|
: SemaRef(SemaRef) {
|
2016-11-03 23:04:58 +08:00
|
|
|
// Don't allow further instantiation if a fatal error and an uncompilable
|
2016-11-04 01:11:28 +08:00
|
|
|
// error have occurred. Any diagnostics we might have raised will not be
|
2016-11-03 23:04:58 +08:00
|
|
|
// visible, and we do not need to construct a correct AST.
|
|
|
|
if (SemaRef.Diags.hasFatalErrorOccurred() &&
|
|
|
|
SemaRef.Diags.hasUncompilableErrorOccurred()) {
|
2015-01-30 13:01:23 +08:00
|
|
|
Invalid = true;
|
|
|
|
return;
|
|
|
|
}
|
2014-03-14 04:34:22 +08:00
|
|
|
Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange);
|
2009-03-11 04:44:00 +08:00
|
|
|
if (!Invalid) {
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext Inst;
|
2014-03-14 04:34:22 +08:00
|
|
|
Inst.Kind = Kind;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.PointOfInstantiation = PointOfInstantiation;
|
2012-11-16 16:40:59 +08:00
|
|
|
Inst.Entity = Entity;
|
2014-03-14 04:34:22 +08:00
|
|
|
Inst.Template = Template;
|
|
|
|
Inst.TemplateArgs = TemplateArgs.data();
|
|
|
|
Inst.NumTemplateArgs = TemplateArgs.size();
|
|
|
|
Inst.DeductionInfo = DeductionInfo;
|
2009-03-11 04:44:00 +08:00
|
|
|
Inst.InstantiationRange = InstantiationRange;
|
2017-02-24 05:43:43 +08:00
|
|
|
SemaRef.pushCodeSynthesisContext(Inst);
|
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
AlreadyInstantiating = !Inst.Entity ? false :
|
2016-08-31 10:15:21 +08:00
|
|
|
!SemaRef.InstantiatingSpecializations
|
|
|
|
.insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
|
|
|
|
.second;
|
2018-02-10 22:04:45 +08:00
|
|
|
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
|
2009-03-11 04:44:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::TemplateInstantiation,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Entity) {}
|
2014-03-14 04:34:22 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionDecl *Entity,
|
|
|
|
ExceptionSpecification, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
2017-02-23 09:43:54 +08:00
|
|
|
SemaRef, CodeSynthesisContext::ExceptionSpecInstantiation,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Entity) {}
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
2016-08-31 10:15:21 +08:00
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param,
|
|
|
|
TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
2015-03-07 00:36:50 +08:00
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::DefaultTemplateArgumentInstantiation,
|
2016-08-31 10:15:21 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, getAsNamedDecl(Param),
|
|
|
|
Template, TemplateArgs) {}
|
2009-03-10 08:06:19 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
FunctionTemplateDecl *FunctionTemplate,
|
|
|
|
ArrayRef<TemplateArgument> TemplateArgs,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::SynthesisKind Kind,
|
2015-03-07 00:36:50 +08:00
|
|
|
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
|
|
|
|
InstantiationRange, FunctionTemplate, nullptr,
|
2016-08-31 10:15:21 +08:00
|
|
|
TemplateArgs, &DeductionInfo) {
|
|
|
|
assert(
|
2017-02-23 09:43:54 +08:00
|
|
|
Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
|
|
|
|
Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution);
|
2016-08-31 10:15:21 +08:00
|
|
|
}
|
2009-07-02 06:01:06 +08:00
|
|
|
|
2016-12-27 15:56:27 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
TemplateDecl *Template,
|
|
|
|
ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
|
2016-12-27 15:56:27 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Template, nullptr,
|
|
|
|
TemplateArgs, &DeductionInfo) {}
|
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
ClassTemplatePartialSpecializationDecl *PartialSpec,
|
|
|
|
ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
|
|
|
|
TemplateArgs, &DeductionInfo) {}
|
2013-08-06 09:03:05 +08:00
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
VarTemplatePartialSpecializationDecl *PartialSpec,
|
|
|
|
ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
|
2015-03-07 00:36:50 +08:00
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, PartialSpec, nullptr,
|
|
|
|
TemplateArgs, &DeductionInfo) {}
|
2009-11-12 03:13:48 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param,
|
|
|
|
ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::DefaultFunctionArgumentInstantiation,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Param, nullptr,
|
|
|
|
TemplateArgs) {}
|
2014-03-14 04:34:22 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
|
|
|
|
NonTypeTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::PriorTemplateArgumentSubstitution,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Param, Template,
|
|
|
|
TemplateArgs) {}
|
2009-11-12 03:13:48 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template,
|
|
|
|
TemplateTemplateParmDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef,
|
2017-02-23 09:43:54 +08:00
|
|
|
CodeSynthesisContext::PriorTemplateArgumentSubstitution,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Param, Template,
|
|
|
|
TemplateArgs) {}
|
2009-11-12 05:54:23 +08:00
|
|
|
|
2015-03-07 00:36:50 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template,
|
|
|
|
NamedDecl *Param, ArrayRef<TemplateArgument> TemplateArgs,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
2017-02-23 09:43:54 +08:00
|
|
|
SemaRef, CodeSynthesisContext::DefaultTemplateArgumentChecking,
|
2015-03-07 00:36:50 +08:00
|
|
|
PointOfInstantiation, InstantiationRange, Param, Template,
|
|
|
|
TemplateArgs) {}
|
2009-09-05 13:14:19 +08:00
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
concepts::Requirement *Req, sema::TemplateDeductionInfo &DeductionInfo,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef, CodeSynthesisContext::RequirementInstantiation,
|
|
|
|
PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
|
|
|
|
/*Template=*/nullptr, /*TemplateArgs=*/None, &DeductionInfo) {}
|
|
|
|
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
concepts::NestedRequirement *Req, ConstraintsCheck,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef, CodeSynthesisContext::NestedRequirementConstraintsCheck,
|
|
|
|
PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr,
|
|
|
|
/*Template=*/nullptr, /*TemplateArgs=*/None) {}
|
|
|
|
|
|
|
|
|
2019-10-15 23:24:26 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
2019-12-06 07:30:21 +08:00
|
|
|
ConstraintsCheck, NamedDecl *Template,
|
2019-10-15 23:24:26 +08:00
|
|
|
ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef, CodeSynthesisContext::ConstraintsCheck,
|
|
|
|
PointOfInstantiation, InstantiationRange, Template, nullptr,
|
|
|
|
TemplateArgs) {}
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
2019-12-06 07:30:21 +08:00
|
|
|
ConstraintSubstitution, NamedDecl *Template,
|
2019-10-15 23:24:26 +08:00
|
|
|
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef, CodeSynthesisContext::ConstraintSubstitution,
|
|
|
|
PointOfInstantiation, InstantiationRange, Template, nullptr,
|
|
|
|
{}, &DeductionInfo) {}
|
|
|
|
|
2019-12-23 14:37:35 +08:00
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
ConstraintNormalization, NamedDecl *Template,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef, CodeSynthesisContext::ConstraintNormalization,
|
|
|
|
PointOfInstantiation, InstantiationRange, Template) {}
|
|
|
|
|
|
|
|
Sema::InstantiatingTemplate::InstantiatingTemplate(
|
|
|
|
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
|
|
|
ParameterMappingSubstitution, NamedDecl *Template,
|
|
|
|
SourceRange InstantiationRange)
|
|
|
|
: InstantiatingTemplate(
|
|
|
|
SemaRef, CodeSynthesisContext::ParameterMappingSubstitution,
|
|
|
|
PointOfInstantiation, InstantiationRange, Template) {}
|
|
|
|
|
2017-02-24 05:43:43 +08:00
|
|
|
void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
|
|
|
|
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
|
|
|
|
InNonInstantiationSFINAEContext = false;
|
|
|
|
|
|
|
|
CodeSynthesisContexts.push_back(Ctx);
|
When we perform dependent name lookup during template instantiation, it's not
sufficient to only consider names visible at the point of instantiation,
because that may not include names that were visible when the template was
defined. More generally, if the instantiation backtrace goes through a module
M, then every declaration visible within M should be available to the
instantiation. Any of those declarations might be part of the interface that M
intended to export to a template that it instantiates.
The fix here has two parts:
1) If we find a non-visible declaration during name lookup during template
instantiation, check whether the declaration was visible from the defining
module of all entities on the active template instantiation stack. The defining
module is not the owning module in all cases: we look at the module in which a
template was defined, not the module in which it was first instantiated.
2) Perform pending instantiations at the end of a module, not at the end of the
translation unit. This is general goodness, since it significantly cuts down
the amount of redundant work that is performed in every TU importing a module,
and also implicitly adds the module containing the point of instantiation to
the set of modules checked for declarations in a lookup within a template
instantiation.
There's a known issue here with template instantiations performed while
building a module, if additional imports are added later on. I'll fix that
in a subsequent commit.
llvm-svn: 187167
2013-07-26 07:08:39 +08:00
|
|
|
|
2017-02-24 05:43:43 +08:00
|
|
|
if (!Ctx.isInstantiationRecord())
|
|
|
|
++NonInstantiationEntries;
|
Improve behavior in the case of stack exhaustion.
Summary:
Clang performs various recursive operations (such as template instantiation),
and may use non-trivial amounts of stack space in each recursive step (for
instance, due to recursive AST walks). While we try to keep the stack space
used by such steps to a minimum and we have explicit limits on the number of
such steps we perform, it's impractical to guarantee that we won't blow out the
stack on deeply recursive template instantiations on complex ASTs, even with
only a moderately high instantiation depth limit.
The user experience in these cases is generally terrible: we crash with
no hint of what went wrong. Under this patch, we attempt to do better:
* Detect when the stack is nearly exhausted, and produce a warning with a
nice template instantiation backtrace, telling the user that we might
run slowly or crash.
* For cases where we're forced to trigger recursive template
instantiation in arbitrarily-deeply-nested contexts, check whether
we're nearly out of stack space and allocate a new stack (by spawning
a new thread) after producing the warning.
Reviewers: rnk, aaron.ballman
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66361
llvm-svn: 369940
2019-08-27 02:18:07 +08:00
|
|
|
|
|
|
|
// Check to see if we're low on stack space. We can't do anything about this
|
|
|
|
// from here, but we can at least warn the user.
|
|
|
|
if (isStackNearlyExhausted())
|
|
|
|
warnStackExhausted(Ctx.PointOfInstantiation);
|
2017-02-24 05:43:43 +08:00
|
|
|
}
|
2017-02-23 10:09:03 +08:00
|
|
|
|
2017-02-24 05:43:43 +08:00
|
|
|
void Sema::popCodeSynthesisContext() {
|
|
|
|
auto &Active = CodeSynthesisContexts.back();
|
|
|
|
if (!Active.isInstantiationRecord()) {
|
|
|
|
assert(NonInstantiationEntries > 0);
|
|
|
|
--NonInstantiationEntries;
|
|
|
|
}
|
|
|
|
|
|
|
|
InNonInstantiationSFINAEContext = Active.SavedInNonInstantiationSFINAEContext;
|
|
|
|
|
|
|
|
// Name lookup no longer looks in this template's defining module.
|
|
|
|
assert(CodeSynthesisContexts.size() >=
|
|
|
|
CodeSynthesisContextLookupModules.size() &&
|
|
|
|
"forgot to remove a lookup module for a template instantiation");
|
|
|
|
if (CodeSynthesisContexts.size() ==
|
|
|
|
CodeSynthesisContextLookupModules.size()) {
|
|
|
|
if (Module *M = CodeSynthesisContextLookupModules.back())
|
|
|
|
LookupModulesCache.erase(M);
|
|
|
|
CodeSynthesisContextLookupModules.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we've left the code synthesis context for the current context stack,
|
|
|
|
// stop remembering that we've emitted that stack.
|
|
|
|
if (CodeSynthesisContexts.size() ==
|
|
|
|
LastEmittedCodeSynthesisContextDepth)
|
|
|
|
LastEmittedCodeSynthesisContextDepth = 0;
|
|
|
|
|
|
|
|
CodeSynthesisContexts.pop_back();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::InstantiatingTemplate::Clear() {
|
|
|
|
if (!Invalid) {
|
|
|
|
if (!AlreadyInstantiating) {
|
|
|
|
auto &Active = SemaRef.CodeSynthesisContexts.back();
|
2020-01-18 15:11:43 +08:00
|
|
|
if (Active.Entity)
|
|
|
|
SemaRef.InstantiatingSpecializations.erase(
|
|
|
|
std::make_pair(Active.Entity, Active.Kind));
|
2017-02-24 05:43:43 +08:00
|
|
|
}
|
|
|
|
|
2018-02-10 22:04:45 +08:00
|
|
|
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
|
|
|
|
SemaRef.CodeSynthesisContexts.back());
|
2016-08-31 10:15:21 +08:00
|
|
|
|
2018-02-10 22:04:45 +08:00
|
|
|
SemaRef.popCodeSynthesisContext();
|
2009-05-19 01:01:57 +08:00
|
|
|
Invalid = true;
|
|
|
|
}
|
2009-03-10 08:06:19 +08:00
|
|
|
}
|
|
|
|
|
2009-03-11 04:44:00 +08:00
|
|
|
bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
SourceRange InstantiationRange) {
|
2009-11-12 05:54:23 +08:00
|
|
|
assert(SemaRef.NonInstantiationEntries <=
|
2017-02-23 09:43:54 +08:00
|
|
|
SemaRef.CodeSynthesisContexts.size());
|
2018-07-31 03:24:48 +08:00
|
|
|
if ((SemaRef.CodeSynthesisContexts.size() -
|
2009-11-12 05:54:23 +08:00
|
|
|
SemaRef.NonInstantiationEntries)
|
2012-03-11 15:00:24 +08:00
|
|
|
<= SemaRef.getLangOpts().InstantiationDepth)
|
2009-03-11 04:44:00 +08:00
|
|
|
return false;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
SemaRef.Diag(PointOfInstantiation,
|
2009-03-11 04:44:00 +08:00
|
|
|
diag::err_template_recursion_depth_exceeded)
|
2012-03-11 15:00:24 +08:00
|
|
|
<< SemaRef.getLangOpts().InstantiationDepth
|
2009-03-11 04:44:00 +08:00
|
|
|
<< InstantiationRange;
|
|
|
|
SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth)
|
2012-03-11 15:00:24 +08:00
|
|
|
<< SemaRef.getLangOpts().InstantiationDepth;
|
2009-03-11 04:44:00 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Prints the current instantiation stack through a series of
|
2009-03-11 02:03:33 +08:00
|
|
|
/// notes.
|
|
|
|
void Sema::PrintInstantiationStack() {
|
2010-04-20 15:18:24 +08:00
|
|
|
// Determine which template instantiations to skip, if any.
|
2017-02-23 09:43:54 +08:00
|
|
|
unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;
|
2010-04-20 15:18:24 +08:00
|
|
|
unsigned Limit = Diags.getTemplateBacktraceLimit();
|
2017-02-23 09:43:54 +08:00
|
|
|
if (Limit && Limit < CodeSynthesisContexts.size()) {
|
2010-04-20 15:18:24 +08:00
|
|
|
SkipStart = Limit / 2 + Limit % 2;
|
2017-02-23 09:43:54 +08:00
|
|
|
SkipEnd = CodeSynthesisContexts.size() - Limit / 2;
|
2010-04-20 15:18:24 +08:00
|
|
|
}
|
|
|
|
|
2009-07-02 06:01:06 +08:00
|
|
|
// FIXME: In all of these cases, we need to show the template arguments
|
2010-04-20 15:18:24 +08:00
|
|
|
unsigned InstantiationIdx = 0;
|
2017-02-23 09:43:54 +08:00
|
|
|
for (SmallVectorImpl<CodeSynthesisContext>::reverse_iterator
|
|
|
|
Active = CodeSynthesisContexts.rbegin(),
|
|
|
|
ActiveEnd = CodeSynthesisContexts.rend();
|
2009-03-11 02:03:33 +08:00
|
|
|
Active != ActiveEnd;
|
2010-04-20 15:18:24 +08:00
|
|
|
++Active, ++InstantiationIdx) {
|
|
|
|
// Skip this instantiation?
|
|
|
|
if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
|
|
|
|
if (InstantiationIdx == SkipStart) {
|
|
|
|
// Note that we're skipping instantiations.
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2010-04-20 15:18:24 +08:00
|
|
|
diag::note_instantiation_contexts_suppressed)
|
2017-02-23 09:43:54 +08:00
|
|
|
<< unsigned(CodeSynthesisContexts.size() - Limit);
|
2010-04-20 15:18:24 +08:00
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-03-11 04:44:00 +08:00
|
|
|
switch (Active->Kind) {
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::TemplateInstantiation: {
|
2012-11-16 16:40:59 +08:00
|
|
|
Decl *D = Active->Entity;
|
2009-05-19 01:01:57 +08:00
|
|
|
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
unsigned DiagID = diag::note_template_member_class_here;
|
|
|
|
if (isa<ClassTemplateSpecializationDecl>(Record))
|
|
|
|
DiagID = diag::note_template_class_instantiation_here;
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation, DiagID)
|
2016-12-24 12:09:05 +08:00
|
|
|
<< Record << Active->InstantiationRange;
|
2009-07-25 04:34:43 +08:00
|
|
|
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
|
2009-06-26 08:10:03 +08:00
|
|
|
unsigned DiagID;
|
|
|
|
if (Function->getPrimaryTemplate())
|
|
|
|
DiagID = diag::note_function_template_spec_here;
|
|
|
|
else
|
|
|
|
DiagID = diag::note_template_member_function_here;
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation, DiagID)
|
2009-05-19 01:01:57 +08:00
|
|
|
<< Function
|
|
|
|
<< Active->InstantiationRange;
|
2011-05-06 05:57:07 +08:00
|
|
|
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2013-08-15 04:15:02 +08:00
|
|
|
VD->isStaticDataMember()?
|
|
|
|
diag::note_template_static_data_member_def_here
|
|
|
|
: diag::note_template_variable_def_here)
|
2011-05-06 05:57:07 +08:00
|
|
|
<< VD
|
|
|
|
<< Active->InstantiationRange;
|
2012-03-15 07:13:10 +08:00
|
|
|
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_template_enum_def_here)
|
|
|
|
<< ED
|
|
|
|
<< Active->InstantiationRange;
|
2014-11-18 07:36:45 +08:00
|
|
|
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_template_nsdmi_here)
|
|
|
|
<< FD << Active->InstantiationRange;
|
2011-05-06 05:57:07 +08:00
|
|
|
} else {
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_template_type_alias_instantiation_here)
|
|
|
|
<< cast<TypeAliasTemplateDecl>(D)
|
2009-07-25 04:34:43 +08:00
|
|
|
<< Active->InstantiationRange;
|
2009-05-19 01:01:57 +08:00
|
|
|
}
|
2009-03-11 04:44:00 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: {
|
2016-08-31 10:15:21 +08:00
|
|
|
TemplateDecl *Template = cast<TemplateDecl>(Active->Template);
|
2013-02-22 23:46:01 +08:00
|
|
|
SmallVector<char, 128> TemplateArgsStr;
|
|
|
|
llvm::raw_svector_ostream OS(TemplateArgsStr);
|
|
|
|
Template->printName(OS);
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Active->template_arguments(),
|
|
|
|
getPrintingPolicy());
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2009-03-11 04:44:00 +08:00
|
|
|
diag::note_default_arg_instantiation_here)
|
2013-02-22 23:46:01 +08:00
|
|
|
<< OS.str()
|
2009-03-11 04:44:00 +08:00
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
2009-06-11 07:47:09 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: {
|
2012-11-16 16:40:59 +08:00
|
|
|
FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity);
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2009-07-02 06:01:06 +08:00
|
|
|
diag::note_explicit_template_arg_substitution_here)
|
2018-07-31 03:24:48 +08:00
|
|
|
<< FnTmpl
|
|
|
|
<< getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
|
|
|
|
Active->TemplateArgs,
|
2010-03-31 04:35:20 +08:00
|
|
|
Active->NumTemplateArgs)
|
|
|
|
<< Active->InstantiationRange;
|
2009-06-11 07:47:09 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: {
|
2016-12-24 12:20:31 +08:00
|
|
|
if (FunctionTemplateDecl *FnTmpl =
|
|
|
|
dyn_cast<FunctionTemplateDecl>(Active->Entity)) {
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2016-12-24 12:20:31 +08:00
|
|
|
diag::note_function_template_deduction_instantiation_here)
|
|
|
|
<< FnTmpl
|
2018-07-31 03:24:48 +08:00
|
|
|
<< getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
|
|
|
|
Active->TemplateArgs,
|
2010-03-31 04:35:20 +08:00
|
|
|
Active->NumTemplateArgs)
|
2009-07-02 06:01:06 +08:00
|
|
|
<< Active->InstantiationRange;
|
|
|
|
} else {
|
2016-12-24 12:20:31 +08:00
|
|
|
bool IsVar = isa<VarTemplateDecl>(Active->Entity) ||
|
|
|
|
isa<VarTemplateSpecializationDecl>(Active->Entity);
|
2016-12-27 15:56:27 +08:00
|
|
|
bool IsTemplate = false;
|
2016-12-24 12:20:31 +08:00
|
|
|
TemplateParameterList *Params;
|
2016-12-27 15:56:27 +08:00
|
|
|
if (auto *D = dyn_cast<TemplateDecl>(Active->Entity)) {
|
|
|
|
IsTemplate = true;
|
|
|
|
Params = D->getTemplateParameters();
|
|
|
|
} else if (auto *D = dyn_cast<ClassTemplatePartialSpecializationDecl>(
|
2016-12-24 12:20:31 +08:00
|
|
|
Active->Entity)) {
|
|
|
|
Params = D->getTemplateParameters();
|
|
|
|
} else if (auto *D = dyn_cast<VarTemplatePartialSpecializationDecl>(
|
|
|
|
Active->Entity)) {
|
|
|
|
Params = D->getTemplateParameters();
|
|
|
|
} else {
|
|
|
|
llvm_unreachable("unexpected template kind");
|
|
|
|
}
|
|
|
|
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2016-12-24 12:20:31 +08:00
|
|
|
diag::note_deduced_template_arg_substitution_here)
|
2016-12-27 15:56:27 +08:00
|
|
|
<< IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
|
2018-07-31 03:24:48 +08:00
|
|
|
<< getTemplateArgumentBindingsText(Params, Active->TemplateArgs,
|
2010-03-31 04:35:20 +08:00
|
|
|
Active->NumTemplateArgs)
|
|
|
|
<< Active->InstantiationRange;
|
2009-07-02 06:01:06 +08:00
|
|
|
}
|
|
|
|
break;
|
2016-12-24 12:20:31 +08:00
|
|
|
}
|
2009-06-11 07:47:09 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: {
|
2012-11-16 16:40:59 +08:00
|
|
|
ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity);
|
2009-09-05 13:14:19 +08:00
|
|
|
FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-02-22 23:46:01 +08:00
|
|
|
SmallVector<char, 128> TemplateArgsStr;
|
|
|
|
llvm::raw_svector_ostream OS(TemplateArgsStr);
|
|
|
|
FD->printName(OS);
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, Active->template_arguments(),
|
|
|
|
getPrintingPolicy());
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2009-09-05 13:14:19 +08:00
|
|
|
diag::note_default_function_arg_instantiation_here)
|
2013-02-22 23:46:01 +08:00
|
|
|
<< OS.str()
|
2009-09-05 13:14:19 +08:00
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::PriorTemplateArgumentSubstitution: {
|
2012-11-16 16:40:59 +08:00
|
|
|
NamedDecl *Parm = cast<NamedDecl>(Active->Entity);
|
2009-11-12 03:13:48 +08:00
|
|
|
std::string Name;
|
|
|
|
if (!Parm->getName().empty())
|
|
|
|
Name = std::string(" '") + Parm->getName().str() + "'";
|
2014-05-26 14:22:03 +08:00
|
|
|
|
|
|
|
TemplateParameterList *TemplateParams = nullptr;
|
2011-01-05 07:35:54 +08:00
|
|
|
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
|
|
|
|
TemplateParams = Template->getTemplateParameters();
|
|
|
|
else
|
|
|
|
TemplateParams =
|
|
|
|
cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
|
|
|
|
->getTemplateParameters();
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2009-11-12 03:13:48 +08:00
|
|
|
diag::note_prior_template_arg_substitution)
|
|
|
|
<< isa<TemplateTemplateParmDecl>(Parm)
|
|
|
|
<< Name
|
2018-07-31 03:24:48 +08:00
|
|
|
<< getTemplateArgumentBindingsText(TemplateParams,
|
|
|
|
Active->TemplateArgs,
|
2009-11-12 03:13:48 +08:00
|
|
|
Active->NumTemplateArgs)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
2009-11-12 05:54:23 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::DefaultTemplateArgumentChecking: {
|
2014-05-26 14:22:03 +08:00
|
|
|
TemplateParameterList *TemplateParams = nullptr;
|
2011-01-05 07:35:54 +08:00
|
|
|
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
|
|
|
|
TemplateParams = Template->getTemplateParameters();
|
|
|
|
else
|
|
|
|
TemplateParams =
|
|
|
|
cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
|
|
|
|
->getTemplateParameters();
|
|
|
|
|
2010-11-19 04:06:41 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
2009-11-12 05:54:23 +08:00
|
|
|
diag::note_template_default_arg_checking)
|
2018-07-31 03:24:48 +08:00
|
|
|
<< getTemplateArgumentBindingsText(TemplateParams,
|
|
|
|
Active->TemplateArgs,
|
2009-11-12 05:54:23 +08:00
|
|
|
Active->NumTemplateArgs)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
|
2018-09-06 06:30:37 +08:00
|
|
|
case CodeSynthesisContext::ExceptionSpecEvaluation:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_evaluating_exception_spec_here)
|
|
|
|
<< cast<FunctionDecl>(Active->Entity);
|
|
|
|
break;
|
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::ExceptionSpecInstantiation:
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_template_exception_spec_instantiation_here)
|
2012-11-16 16:40:59 +08:00
|
|
|
<< cast<FunctionDecl>(Active->Entity)
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
2017-02-24 05:43:43 +08:00
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
case CodeSynthesisContext::RequirementInstantiation:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_template_requirement_instantiation_here)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CodeSynthesisContext::NestedRequirementConstraintsCheck:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_nested_requirement_here)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
|
2017-02-24 05:43:43 +08:00
|
|
|
case CodeSynthesisContext::DeclaringSpecialMember:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_in_declaration_of_implicit_special_member)
|
|
|
|
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
|
|
|
|
break;
|
2017-05-26 06:47:05 +08:00
|
|
|
|
2019-12-11 08:45:02 +08:00
|
|
|
case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
|
|
|
|
Diags.Report(Active->Entity->getLocation(),
|
|
|
|
diag::note_in_declaration_of_implicit_equality_comparison);
|
|
|
|
break;
|
|
|
|
|
2018-02-10 22:04:45 +08:00
|
|
|
case CodeSynthesisContext::DefiningSynthesizedFunction: {
|
2019-12-05 07:25:27 +08:00
|
|
|
// FIXME: For synthesized functions that are not defaulted,
|
|
|
|
// produce a note.
|
|
|
|
auto *FD = dyn_cast<FunctionDecl>(Active->Entity);
|
|
|
|
DefaultedFunctionKind DFK =
|
|
|
|
FD ? getDefaultedFunctionKind(FD) : DefaultedFunctionKind();
|
|
|
|
if (DFK.isSpecialMember()) {
|
|
|
|
auto *MD = cast<CXXMethodDecl>(FD);
|
2017-05-26 06:47:05 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_member_synthesized_at)
|
2019-12-05 07:25:27 +08:00
|
|
|
<< MD->isExplicitlyDefaulted() << DFK.asSpecialMember()
|
|
|
|
<< Context.getTagDeclType(MD->getParent());
|
|
|
|
} else if (DFK.isComparison()) {
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_comparison_synthesized_at)
|
|
|
|
<< (int)DFK.asComparison()
|
|
|
|
<< Context.getTagDeclType(
|
|
|
|
cast<CXXRecordDecl>(FD->getLexicalDeclContext()));
|
2017-05-26 06:47:05 +08:00
|
|
|
}
|
|
|
|
break;
|
2009-03-11 04:44:00 +08:00
|
|
|
}
|
2018-02-10 22:04:45 +08:00
|
|
|
|
2019-10-19 08:04:43 +08:00
|
|
|
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
|
|
|
|
Diags.Report(Active->Entity->getLocation(),
|
|
|
|
diag::note_rewriting_operator_as_spaceship);
|
|
|
|
break;
|
|
|
|
|
2018-02-10 22:04:45 +08:00
|
|
|
case CodeSynthesisContext::Memoization:
|
|
|
|
break;
|
2019-10-15 23:24:26 +08:00
|
|
|
|
2019-12-06 07:30:21 +08:00
|
|
|
case CodeSynthesisContext::ConstraintsCheck: {
|
|
|
|
unsigned DiagID = 0;
|
2020-01-26 04:54:27 +08:00
|
|
|
if (!Active->Entity) {
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_nested_requirement_here)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
}
|
2019-12-06 07:30:21 +08:00
|
|
|
if (isa<ConceptDecl>(Active->Entity))
|
|
|
|
DiagID = diag::note_concept_specialization_here;
|
|
|
|
else if (isa<TemplateDecl>(Active->Entity))
|
|
|
|
DiagID = diag::note_checking_constraints_for_template_id_here;
|
|
|
|
else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
|
|
|
|
DiagID = diag::note_checking_constraints_for_var_spec_id_here;
|
2020-01-26 04:54:27 +08:00
|
|
|
else if (isa<ClassTemplatePartialSpecializationDecl>(Active->Entity))
|
2019-12-06 07:30:21 +08:00
|
|
|
DiagID = diag::note_checking_constraints_for_class_spec_id_here;
|
2020-01-26 04:54:27 +08:00
|
|
|
else {
|
|
|
|
assert(isa<FunctionDecl>(Active->Entity));
|
|
|
|
DiagID = diag::note_checking_constraints_for_function_here;
|
2019-10-15 23:24:26 +08:00
|
|
|
}
|
2019-12-06 07:30:21 +08:00
|
|
|
SmallVector<char, 128> TemplateArgsStr;
|
|
|
|
llvm::raw_svector_ostream OS(TemplateArgsStr);
|
|
|
|
cast<NamedDecl>(Active->Entity)->printName(OS);
|
2020-01-26 04:54:27 +08:00
|
|
|
if (!isa<FunctionDecl>(Active->Entity))
|
|
|
|
printTemplateArgumentList(OS, Active->template_arguments(),
|
|
|
|
getPrintingPolicy());
|
2019-12-06 07:30:21 +08:00
|
|
|
Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
|
|
|
|
<< Active->InstantiationRange;
|
2019-10-15 23:24:26 +08:00
|
|
|
break;
|
2019-12-06 07:30:21 +08:00
|
|
|
}
|
2019-10-15 23:24:26 +08:00
|
|
|
case CodeSynthesisContext::ConstraintSubstitution:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_constraint_substitution_here)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
2019-12-23 14:37:35 +08:00
|
|
|
case CodeSynthesisContext::ConstraintNormalization:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_constraint_normalization_here)
|
|
|
|
<< cast<NamedDecl>(Active->Entity)->getName()
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
|
|
|
case CodeSynthesisContext::ParameterMappingSubstitution:
|
|
|
|
Diags.Report(Active->PointOfInstantiation,
|
|
|
|
diag::note_parameter_mapping_substitution_here)
|
|
|
|
<< Active->InstantiationRange;
|
|
|
|
break;
|
2018-02-10 22:04:45 +08:00
|
|
|
}
|
2009-03-11 02:03:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
|
2011-01-28 06:31:44 +08:00
|
|
|
if (InNonInstantiationSFINAEContext)
|
2014-05-26 14:22:03 +08:00
|
|
|
return Optional<TemplateDeductionInfo *>(nullptr);
|
2011-01-28 06:31:44 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
for (SmallVectorImpl<CodeSynthesisContext>::const_reverse_iterator
|
|
|
|
Active = CodeSynthesisContexts.rbegin(),
|
|
|
|
ActiveEnd = CodeSynthesisContexts.rend();
|
2009-06-14 15:33:30 +08:00
|
|
|
Active != ActiveEnd;
|
2018-07-31 03:24:48 +08:00
|
|
|
++Active)
|
2009-11-12 05:54:23 +08:00
|
|
|
{
|
2017-02-24 05:43:43 +08:00
|
|
|
switch (Active->Kind) {
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::TemplateInstantiation:
|
2012-04-26 15:24:08 +08:00
|
|
|
// An instantiation of an alias template may or may not be a SFINAE
|
|
|
|
// context, depending on what else is on the stack.
|
2012-11-16 16:40:59 +08:00
|
|
|
if (isa<TypeAliasTemplateDecl>(Active->Entity))
|
2012-04-26 15:24:08 +08:00
|
|
|
break;
|
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-02 03:54:45 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
|
|
|
|
case CodeSynthesisContext::ExceptionSpecInstantiation:
|
2019-10-15 23:24:26 +08:00
|
|
|
case CodeSynthesisContext::ConstraintsCheck:
|
2019-12-23 14:37:35 +08:00
|
|
|
case CodeSynthesisContext::ParameterMappingSubstitution:
|
|
|
|
case CodeSynthesisContext::ConstraintNormalization:
|
2020-01-18 15:11:43 +08:00
|
|
|
case CodeSynthesisContext::NestedRequirementConstraintsCheck:
|
2009-07-02 06:01:06 +08:00
|
|
|
// This is a template instantiation, so there is no SFINAE.
|
2013-02-21 09:47:18 +08:00
|
|
|
return None;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::DefaultTemplateArgumentInstantiation:
|
|
|
|
case CodeSynthesisContext::PriorTemplateArgumentSubstitution:
|
|
|
|
case CodeSynthesisContext::DefaultTemplateArgumentChecking:
|
2009-11-12 03:13:48 +08:00
|
|
|
// A default template argument instantiation and substitution into
|
2018-07-31 03:24:48 +08:00
|
|
|
// template parameters with arguments for prior parameters may or may
|
2009-11-12 03:13:48 +08:00
|
|
|
// not be a SFINAE context; look further up the stack.
|
2009-06-14 15:33:30 +08:00
|
|
|
break;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2017-02-23 09:43:54 +08:00
|
|
|
case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
|
|
|
|
case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
|
2019-10-15 23:24:26 +08:00
|
|
|
case CodeSynthesisContext::ConstraintSubstitution:
|
2020-01-18 15:11:43 +08:00
|
|
|
case CodeSynthesisContext::RequirementInstantiation:
|
|
|
|
// We're either substituting explicitly-specified template arguments,
|
|
|
|
// deduced template arguments, a constraint expression or a requirement
|
|
|
|
// in a requires expression, so SFINAE applies.
|
2010-10-13 07:32:35 +08:00
|
|
|
assert(Active->DeductionInfo && "Missing deduction info pointer");
|
|
|
|
return Active->DeductionInfo;
|
2017-02-24 05:43:43 +08:00
|
|
|
|
|
|
|
case CodeSynthesisContext::DeclaringSpecialMember:
|
2019-12-11 08:45:02 +08:00
|
|
|
case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
|
2017-05-26 06:47:05 +08:00
|
|
|
case CodeSynthesisContext::DefiningSynthesizedFunction:
|
2019-10-19 08:04:43 +08:00
|
|
|
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
|
2017-02-24 05:43:43 +08:00
|
|
|
// This happens in a context unrelated to template instantiation, so
|
|
|
|
// there is no SFINAE.
|
|
|
|
return None;
|
2018-02-10 22:04:45 +08:00
|
|
|
|
2018-09-06 06:30:37 +08:00
|
|
|
case CodeSynthesisContext::ExceptionSpecEvaluation:
|
|
|
|
// FIXME: This should not be treated as a SFINAE context, because
|
|
|
|
// we will cache an incorrect exception specification. However, clang
|
|
|
|
// bootstrap relies this! See PR31692.
|
|
|
|
break;
|
|
|
|
|
2018-02-10 22:04:45 +08:00
|
|
|
case CodeSynthesisContext::Memoization:
|
|
|
|
break;
|
2009-06-14 15:33:30 +08:00
|
|
|
}
|
2017-02-24 05:43:43 +08:00
|
|
|
|
|
|
|
// The inner context was transparent for SFINAE. If it occurred within a
|
|
|
|
// non-instantiation SFINAE context, then SFINAE applies.
|
|
|
|
if (Active->SavedInNonInstantiationSFINAEContext)
|
|
|
|
return Optional<TemplateDeductionInfo *>(nullptr);
|
2009-06-14 15:33:30 +08:00
|
|
|
}
|
|
|
|
|
2013-02-21 09:47:18 +08:00
|
|
|
return None;
|
2009-06-14 15:33:30 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 03:31:52 +08:00
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
// Template Instantiation for Types
|
|
|
|
//===----------------------------------------------------------------------===/
|
2009-02-28 08:25:32 +08:00
|
|
|
namespace {
|
2010-05-01 02:55:50 +08:00
|
|
|
class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs;
|
2009-02-28 08:25:32 +08:00
|
|
|
SourceLocation Loc;
|
|
|
|
DeclarationName Entity;
|
|
|
|
|
|
|
|
public:
|
2009-08-20 15:17:43 +08:00
|
|
|
typedef TreeTransform<TemplateInstantiator> inherited;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
TemplateInstantiator(Sema &SemaRef,
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
2009-08-05 00:50:30 +08:00
|
|
|
SourceLocation Loc,
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclarationName Entity)
|
|
|
|
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
|
2009-08-20 15:17:43 +08:00
|
|
|
Entity(Entity) { }
|
2009-08-05 00:50:30 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Determine whether the given type \p T has already been
|
2009-08-05 00:50:30 +08:00
|
|
|
/// transformed.
|
|
|
|
///
|
|
|
|
/// For the purposes of template instantiation, a type has already been
|
|
|
|
/// transformed if it is NULL or if it is not dependent.
|
2010-05-08 07:12:07 +08:00
|
|
|
bool AlreadyTransformed(QualType T);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Returns the location of the entity being instantiated, if known.
|
2009-08-05 00:50:30 +08:00
|
|
|
SourceLocation getBaseLocation() { return Loc; }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Returns the name of the entity being instantiated, if any.
|
2009-08-05 00:50:30 +08:00
|
|
|
DeclarationName getBaseEntity() { return Entity; }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Sets the "base" location and entity when that
|
2009-10-27 14:26:26 +08:00
|
|
|
/// information is known based on another transformation.
|
|
|
|
void setBase(SourceLocation Loc, DeclarationName Entity) {
|
|
|
|
this->Loc = Loc;
|
|
|
|
this->Entity = Entity;
|
|
|
|
}
|
2010-12-21 06:05:00 +08:00
|
|
|
|
|
|
|
bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
|
|
|
|
SourceRange PatternRange,
|
2013-08-10 02:02:13 +08:00
|
|
|
ArrayRef<UnexpandedParameterPack> Unexpanded,
|
|
|
|
bool &ShouldExpand, bool &RetainExpansion,
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<unsigned> &NumExpansions) {
|
2018-07-31 03:24:48 +08:00
|
|
|
return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
|
2010-12-21 08:52:54 +08:00
|
|
|
PatternRange, Unexpanded,
|
2018-07-31 03:24:48 +08:00
|
|
|
TemplateArgs,
|
2010-12-21 08:52:54 +08:00
|
|
|
ShouldExpand,
|
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 15:32:04 +08:00
|
|
|
RetainExpansion,
|
2010-12-21 08:52:54 +08:00
|
|
|
NumExpansions);
|
|
|
|
}
|
2010-12-21 06:05:00 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
|
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-08 00:43:16 +08:00
|
|
|
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
|
|
|
|
}
|
2018-07-31 03:24:48 +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 15:32:04 +08:00
|
|
|
TemplateArgument ForgetPartiallySubstitutedPack() {
|
|
|
|
TemplateArgument Result;
|
|
|
|
if (NamedDecl *PartialPack
|
|
|
|
= SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
|
|
|
|
MultiLevelTemplateArgumentList &TemplateArgs
|
|
|
|
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
|
|
|
|
unsigned Depth, Index;
|
2014-03-02 21:01:17 +08:00
|
|
|
std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
|
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 15:32:04 +08:00
|
|
|
if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
|
|
|
|
Result = TemplateArgs(Depth, Index);
|
|
|
|
TemplateArgs.setArgument(Depth, Index, TemplateArgument());
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +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 15:32:04 +08:00
|
|
|
return Result;
|
|
|
|
}
|
2018-07-31 03:24:48 +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 15:32:04 +08:00
|
|
|
void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
|
|
|
|
if (Arg.isNull())
|
|
|
|
return;
|
2018-07-31 03:24:48 +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 15:32:04 +08:00
|
|
|
if (NamedDecl *PartialPack
|
|
|
|
= SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
|
|
|
|
MultiLevelTemplateArgumentList &TemplateArgs
|
|
|
|
= const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
|
|
|
|
unsigned Depth, Index;
|
2014-03-02 21:01:17 +08:00
|
|
|
std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
|
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 15:32:04 +08:00
|
|
|
TemplateArgs.setArgument(Depth, Index, Arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Transform the given declaration by instantiating a reference to
|
2009-08-05 00:50:30 +08:00
|
|
|
/// this declaration.
|
2010-03-01 23:56:25 +08:00
|
|
|
Decl *TransformDecl(SourceLocation Loc, Decl *D);
|
2009-08-11 13:31:07 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void transformAttrs(Decl *Old, Decl *New) {
|
2012-02-14 06:00:16 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
|
|
|
|
}
|
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
|
|
|
|
if (Old->isParameterPack()) {
|
|
|
|
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
|
|
|
|
for (auto *New : NewDecls)
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
|
|
|
|
Old, cast<VarDecl>(New));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(NewDecls.size() == 1 &&
|
|
|
|
"should only have multiple expansions for a pack");
|
|
|
|
Decl *New = NewDecls.front();
|
|
|
|
|
2015-04-28 05:27:54 +08:00
|
|
|
// If we've instantiated the call operator of a lambda or the call
|
|
|
|
// operator template of a generic lambda, update the "instantiation of"
|
|
|
|
// information.
|
|
|
|
auto *NewMD = dyn_cast<CXXMethodDecl>(New);
|
|
|
|
if (NewMD && isLambdaCallOperator(NewMD)) {
|
|
|
|
auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
|
|
|
|
if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
|
|
|
|
NewTD->setInstantiatedFromMemberTemplate(
|
|
|
|
OldMD->getDescribedFunctionTemplate());
|
|
|
|
else
|
|
|
|
NewMD->setInstantiationOfMemberFunction(OldMD,
|
|
|
|
TSK_ImplicitInstantiation);
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-02-14 06:00:16 +08:00
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
|
2016-03-24 04:07:07 +08:00
|
|
|
|
|
|
|
// We recreated a local declaration, but not by instantiating it. There
|
|
|
|
// may be pending dependent diagnostics to produce.
|
|
|
|
if (auto *DC = dyn_cast<DeclContext>(Old))
|
|
|
|
SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
|
2012-02-14 06:00:16 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Transform the definition of the given declaration by
|
2009-08-20 15:17:43 +08:00
|
|
|
/// instantiating it.
|
2010-03-02 01:25:41 +08:00
|
|
|
Decl *TransformDefinition(SourceLocation Loc, Decl *D);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Transform the first qualifier within a scope by instantiating the
|
2009-10-20 13:58:46 +08:00
|
|
|
/// declaration.
|
|
|
|
NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Rebuild the exception declaration and register the declaration
|
2009-08-20 15:17:43 +08:00
|
|
|
/// as an instantiated local.
|
2018-07-31 03:24:48 +08:00
|
|
|
VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *Declarator,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
IdentifierInfo *Name);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
/// Rebuild the Objective-C exception declaration and register the
|
2010-04-27 01:57:08 +08:00
|
|
|
/// declaration as an instantiated local.
|
2018-07-31 03:24:48 +08:00
|
|
|
VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
|
2010-04-27 01:57:08 +08:00
|
|
|
TypeSourceInfo *TSInfo, QualType T);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Check for tag mismatches when instantiating an
|
2009-09-11 12:59:25 +08:00
|
|
|
/// elaborated type.
|
2010-11-05 03:04:38 +08:00
|
|
|
QualType RebuildElaboratedType(SourceLocation KeywordLoc,
|
|
|
|
ElaboratedTypeKeyword Keyword,
|
2011-03-02 02:12:44 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
|
|
|
QualType T);
|
2009-09-11 12:59:25 +08:00
|
|
|
|
2014-05-26 14:22:03 +08:00
|
|
|
TemplateName
|
|
|
|
TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
QualType ObjectType = QualType(),
|
2017-01-20 08:20:39 +08:00
|
|
|
NamedDecl *FirstQualifierInScope = nullptr,
|
|
|
|
bool AllowInjectedClassName = false);
|
2011-03-03 02:07:45 +08:00
|
|
|
|
2014-10-13 04:46:07 +08:00
|
|
|
const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
|
|
|
|
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
|
|
|
|
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
|
2012-09-12 08:56:43 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
|
2010-12-24 08:15:10 +08:00
|
|
|
NonTypeTemplateParmDecl *D);
|
2011-01-15 09:15:58 +08:00
|
|
|
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
|
|
|
|
SubstNonTypeTemplateParmPackExpr *E);
|
2020-01-31 21:55:06 +08:00
|
|
|
ExprResult TransformSubstNonTypeTemplateParmExpr(
|
|
|
|
SubstNonTypeTemplateParmExpr *E);
|
2012-09-12 08:56:43 +08:00
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
/// Rebuild a DeclRefExpr for a VarDecl reference.
|
|
|
|
ExprResult RebuildVarDeclRefExpr(VarDecl *PD, SourceLocation Loc);
|
2012-09-12 08:56:43 +08:00
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
/// Transform a reference to a function or init-capture parameter pack.
|
|
|
|
ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, VarDecl *PD);
|
2012-09-12 08:56:43 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Transform a FunctionParmPackExpr which was built when we couldn't
|
2012-09-12 08:56:43 +08:00
|
|
|
/// expand a function parameter pack reference which refers to an expanded
|
|
|
|
/// pack.
|
|
|
|
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
|
|
|
|
|
Revert r217995 and follow-ups:
r218053: Use exceptions() instead of getNumExceptions()/getExceptionType() to avoid
r218011: Work around MSVC parser bug by putting redundant braces around the body of
r217997: Skip parens when detecting whether we're instantiating a function declaration.
r217995: Instantiate exception specifications when instantiating function types (other
The Windows build was broken for 16 hours and no one had any good ideas of how to
fix it. Reverting for now to make the builders green. See the cfe-commits thread [1] for
more info.
This was the build error (from [2]):
C:\bb-win7\ninja-clang-i686-msc17-R\llvm-project\clang\lib\Sema\SemaTemplateInstantiate.cpp(1590) : error C2668: '`anonymous-namespace'::TemplateInstantiator::TransformFunctionProtoType' : ambiguous call to overloaded function
C:\bb-win7\ninja-clang-i686-msc17-R\llvm-project\clang\lib\Sema\SemaTemplateInstantiate.cpp(1313): could be 'clang::QualType `anonymous-namespace'::TemplateInstantiator::TransformFunctionProtoType<clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>>(clang::TypeLocBuilder &,clang::FunctionProtoTypeLoc,clang::CXXRecordDecl *,unsigned int,Fn)'
with
[
Fn=clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>
]
c:\bb-win7\ninja-clang-i686-msc17-r\llvm-project\clang\lib\sema\TreeTransform.h(4532): or 'clang::QualType clang::TreeTransform<Derived>::TransformFunctionProtoType<clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>>(clang::TypeLocBuilder &,clang::FunctionProtoTypeLoc,clang::CXXRecordDecl *,unsigned int,Fn)'
with
[
Derived=`anonymous-namespace'::TemplateInstantiator,
Fn=clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>
]
while trying to match the argument list '(clang::TypeLocBuilder, clang::FunctionProtoTypeLoc, clang::CXXRecordDecl *, unsigned int, clang::Sema::SubstFunctionDeclType::<lambda_756edcbe7bd5c7584849a6e3a1491735>)'
1. http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20140915/115011.html
2. http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/10515/steps/build_clang_tools_1/logs/stdio
llvm-svn: 218058
2014-09-19 00:01:32 +08:00
|
|
|
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
2014-11-12 10:00:47 +08:00
|
|
|
FunctionProtoTypeLoc TL) {
|
|
|
|
// Call the base version; it will forward to our overridden version below.
|
|
|
|
return inherited::TransformFunctionProtoType(TLB, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Fn>
|
2012-04-16 15:05:22 +08:00
|
|
|
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
|
|
|
FunctionProtoTypeLoc TL,
|
|
|
|
CXXRecordDecl *ThisContext,
|
2018-12-13 18:15:27 +08:00
|
|
|
Qualifiers ThisTypeQuals,
|
2014-11-12 10:00:47 +08:00
|
|
|
Fn TransformExceptionSpec);
|
2012-04-16 15:05:22 +08:00
|
|
|
|
2011-01-15 06:40:04 +08:00
|
|
|
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
|
2011-05-02 06:35:37 +08:00
|
|
|
int indexAdjustment,
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<unsigned> NumExpansions,
|
2012-01-26 00:15:54 +08:00
|
|
|
bool ExpectParameterPack);
|
2010-03-11 17:03:00 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Transforms a template type parameter type by performing
|
2009-08-05 00:50:30 +08:00
|
|
|
/// substitution of the corresponding template type argument.
|
2009-10-21 08:40:46 +08:00
|
|
|
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
2010-11-12 16:19:04 +08:00
|
|
|
TemplateTypeParmTypeLoc TL);
|
2010-07-07 03:51:49 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Transforms an already-substituted template type parameter pack
|
2011-01-14 10:55:32 +08:00
|
|
|
/// into either itself (if we aren't substituting into its pack expansion)
|
|
|
|
/// or the appropriate substituted argument.
|
|
|
|
QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
|
|
|
|
SubstTemplateTypeParmPackTypeLoc TL);
|
|
|
|
|
2012-07-25 11:56:55 +08:00
|
|
|
ExprResult TransformLambdaExpr(LambdaExpr *E) {
|
|
|
|
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
|
|
|
|
return TreeTransform<TemplateInstantiator>::TransformLambdaExpr(E);
|
|
|
|
}
|
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
ExprResult TransformRequiresExpr(RequiresExpr *E) {
|
|
|
|
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
|
|
|
|
return TreeTransform<TemplateInstantiator>::TransformRequiresExpr(E);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TransformRequiresExprRequirements(
|
|
|
|
ArrayRef<concepts::Requirement *> Reqs,
|
|
|
|
SmallVectorImpl<concepts::Requirement *> &Transformed) {
|
|
|
|
bool SatisfactionDetermined = false;
|
|
|
|
for (concepts::Requirement *Req : Reqs) {
|
|
|
|
concepts::Requirement *TransReq = nullptr;
|
|
|
|
if (!SatisfactionDetermined) {
|
|
|
|
if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
|
|
|
|
TransReq = TransformTypeRequirement(TypeReq);
|
|
|
|
else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
|
|
|
|
TransReq = TransformExprRequirement(ExprReq);
|
|
|
|
else
|
|
|
|
TransReq = TransformNestedRequirement(
|
|
|
|
cast<concepts::NestedRequirement>(Req));
|
|
|
|
if (!TransReq)
|
|
|
|
return true;
|
|
|
|
if (!TransReq->isDependent() && !TransReq->isSatisfied())
|
|
|
|
// [expr.prim.req]p6
|
|
|
|
// [...] The substitution and semantic constraint checking
|
|
|
|
// proceeds in lexical order and stops when a condition that
|
|
|
|
// determines the result of the requires-expression is
|
|
|
|
// encountered. [..]
|
|
|
|
SatisfactionDetermined = true;
|
|
|
|
} else
|
|
|
|
TransReq = Req;
|
|
|
|
Transformed.push_back(TransReq);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-03-03 02:46:05 +08:00
|
|
|
TemplateParameterList *TransformTemplateParameterList(
|
2013-10-23 14:44:28 +08:00
|
|
|
TemplateParameterList *OrigTPL) {
|
|
|
|
if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-10-23 14:44:28 +08:00
|
|
|
DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
|
2018-07-31 03:24:48 +08:00
|
|
|
TemplateDeclInstantiator DeclInstantiator(getSema(),
|
2013-10-23 14:44:28 +08:00
|
|
|
/* DeclContext *Owner */ Owner, TemplateArgs);
|
2018-07-31 03:24:48 +08:00
|
|
|
return DeclInstantiator.SubstTemplateParams(OrigTPL);
|
2012-07-25 11:56:55 +08:00
|
|
|
}
|
2020-01-18 15:11:43 +08:00
|
|
|
|
|
|
|
concepts::TypeRequirement *
|
|
|
|
TransformTypeRequirement(concepts::TypeRequirement *Req);
|
|
|
|
concepts::ExprRequirement *
|
|
|
|
TransformExprRequirement(concepts::ExprRequirement *Req);
|
|
|
|
concepts::NestedRequirement *
|
|
|
|
TransformNestedRequirement(concepts::NestedRequirement *Req);
|
|
|
|
|
2011-07-15 13:09:51 +08:00
|
|
|
private:
|
|
|
|
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
|
|
|
|
SourceLocation loc,
|
2012-07-09 11:07:20 +08:00
|
|
|
TemplateArgument arg);
|
2009-05-14 02:28:20 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2010-05-08 07:12:07 +08:00
|
|
|
bool TemplateInstantiator::AlreadyTransformed(QualType T) {
|
|
|
|
if (T.isNull())
|
|
|
|
return true;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-07-01 09:22:09 +08:00
|
|
|
if (T->isInstantiationDependentType() || T->isVariablyModifiedType())
|
2010-05-08 07:12:07 +08:00
|
|
|
return false;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-05-08 07:12:07 +08:00
|
|
|
getSema().MarkDeclarationsReferencedInType(Loc, T);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-07-20 03:40:38 +08:00
|
|
|
static TemplateArgument
|
|
|
|
getPackSubstitutedTemplateArgument(Sema &S, TemplateArgument Arg) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(S.ArgumentPackSubstitutionIndex >= 0);
|
2013-07-20 03:40:38 +08:00
|
|
|
assert(S.ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
|
|
|
|
Arg = Arg.pack_begin()[S.ArgumentPackSubstitutionIndex];
|
|
|
|
if (Arg.isPackExpansion())
|
|
|
|
Arg = Arg.getPackExpansionPattern();
|
|
|
|
return Arg;
|
|
|
|
}
|
|
|
|
|
2010-03-01 23:56:25 +08:00
|
|
|
Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
|
2009-09-04 05:38:09 +08:00
|
|
|
if (!D)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-04 05:38:09 +08:00
|
|
|
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
|
2009-08-29 04:31:08 +08:00
|
|
|
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
|
2010-02-06 03:54:12 +08:00
|
|
|
// If the corresponding template argument is NULL or non-existent, it's
|
|
|
|
// because we are performing instantiation from explicitly-specified
|
|
|
|
// template arguments in a function template, but there were some
|
|
|
|
// arguments left unspecified.
|
|
|
|
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
|
|
|
|
TTP->getPosition()))
|
|
|
|
return D;
|
|
|
|
|
2011-01-05 23:48:55 +08:00
|
|
|
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-05 23:48:55 +08:00
|
|
|
if (TTP->isParameterPack()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(Arg.getKind() == TemplateArgument::Pack &&
|
2011-01-05 23:48:55 +08:00
|
|
|
"Missing argument pack");
|
2013-07-20 03:40:38 +08:00
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2011-01-05 23:48:55 +08:00
|
|
|
}
|
|
|
|
|
2017-08-30 06:14:43 +08:00
|
|
|
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
|
2009-11-11 09:00:40 +08:00
|
|
|
assert(!Template.isNull() && Template.getAsTemplateDecl() &&
|
2009-08-29 04:31:08 +08:00
|
|
|
"Wrong kind of template template argument");
|
2009-11-11 09:00:40 +08:00
|
|
|
return Template.getAsTemplateDecl();
|
2009-08-29 04:31:08 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-11-11 09:00:40 +08:00
|
|
|
// Fall through to find the instantiated declaration for this template
|
|
|
|
// template parameter.
|
2009-08-06 14:41:21 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-01 23:56:25 +08:00
|
|
|
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
|
|
|
|
2010-03-02 01:25:41 +08:00
|
|
|
Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
|
2009-08-26 06:02:44 +08:00
|
|
|
Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
|
2009-08-20 15:17:43 +08:00
|
|
|
if (!Inst)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-20 15:17:43 +08:00
|
|
|
getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst);
|
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2009-10-20 13:58:46 +08:00
|
|
|
NamedDecl *
|
2018-07-31 03:24:48 +08:00
|
|
|
TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
|
2009-10-20 13:58:46 +08:00
|
|
|
SourceLocation Loc) {
|
2018-07-31 03:24:48 +08:00
|
|
|
// If the first part of the nested-name-specifier was a template type
|
2009-10-20 13:58:46 +08:00
|
|
|
// parameter, instantiate that type parameter down to a tag type.
|
|
|
|
if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
|
2018-07-31 03:24:48 +08:00
|
|
|
const TemplateTypeParmType *TTP
|
2009-10-20 13:58:46 +08:00
|
|
|
= cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-20 13:58:46 +08:00
|
|
|
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
|
2010-12-21 06:48:17 +08:00
|
|
|
// FIXME: This needs testing w/ member access expressions.
|
|
|
|
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-21 06:48:17 +08:00
|
|
|
if (TTP->isParameterPack()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(Arg.getKind() == TemplateArgument::Pack &&
|
2010-12-21 06:48:17 +08:00
|
|
|
"Missing argument pack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-15 07:41:42 +08:00
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2013-07-20 03:40:38 +08:00
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2010-12-21 06:48:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType T = Arg.getAsType();
|
2009-10-20 13:58:46 +08:00
|
|
|
if (T.isNull())
|
2010-03-01 23:56:25 +08:00
|
|
|
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-20 13:58:46 +08:00
|
|
|
if (const TagType *Tag = T->getAs<TagType>())
|
|
|
|
return Tag->getDecl();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-20 13:58:46 +08:00
|
|
|
// The resulting type is not a tag; complain.
|
|
|
|
getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2009-10-20 13:58:46 +08:00
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-03-01 23:56:25 +08:00
|
|
|
return cast_or_null<NamedDecl>(TransformDecl(Loc, D));
|
2009-10-20 13:58:46 +08:00
|
|
|
}
|
|
|
|
|
2009-08-20 15:17:43 +08:00
|
|
|
VarDecl *
|
|
|
|
TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *Declarator,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation NameLoc,
|
|
|
|
IdentifierInfo *Name) {
|
2010-09-10 01:09:21 +08:00
|
|
|
VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator,
|
2011-03-08 16:55:46 +08:00
|
|
|
StartLoc, NameLoc, Name);
|
2010-04-27 01:57:08 +08:00
|
|
|
if (Var)
|
|
|
|
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
|
|
|
|
return Var;
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
|
|
|
|
TypeSourceInfo *TSInfo,
|
2010-04-27 01:57:08 +08:00
|
|
|
QualType T) {
|
|
|
|
VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T);
|
|
|
|
if (Var)
|
2009-08-20 15:17:43 +08:00
|
|
|
getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
|
|
|
|
return Var;
|
|
|
|
}
|
|
|
|
|
2009-09-11 12:59:25 +08:00
|
|
|
QualType
|
2010-11-05 03:04:38 +08:00
|
|
|
TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
|
|
|
|
ElaboratedTypeKeyword Keyword,
|
2011-03-02 02:12:44 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc,
|
2010-05-12 05:36:43 +08:00
|
|
|
QualType T) {
|
2009-09-11 12:59:25 +08:00
|
|
|
if (const TagType *TT = T->getAs<TagType>()) {
|
|
|
|
TagDecl* TD = TT->getDecl();
|
|
|
|
|
2010-11-05 03:04:38 +08:00
|
|
|
SourceLocation TagLocation = KeywordLoc;
|
2009-09-11 12:59:25 +08:00
|
|
|
|
|
|
|
IdentifierInfo *Id = TD->getIdentifier();
|
|
|
|
|
|
|
|
// TODO: should we even warn on struct/class mismatches for this? Seems
|
|
|
|
// like it's likely to produce a lot of spurious errors.
|
2012-08-17 08:12:27 +08:00
|
|
|
if (Id && Keyword != ETK_None && Keyword != ETK_Typename) {
|
2010-05-12 05:36:43 +08:00
|
|
|
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword);
|
2011-06-10 11:11:26 +08:00
|
|
|
if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false,
|
2015-07-11 07:05:47 +08:00
|
|
|
TagLocation, Id)) {
|
2010-05-12 05:36:43 +08:00
|
|
|
SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag)
|
|
|
|
<< Id
|
|
|
|
<< FixItHint::CreateReplacement(SourceRange(TagLocation),
|
|
|
|
TD->getKindName());
|
|
|
|
SemaRef.Diag(TD->getLocation(), diag::note_previous_use);
|
|
|
|
}
|
2009-09-11 12:59:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-05 03:04:38 +08:00
|
|
|
return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(KeywordLoc,
|
|
|
|
Keyword,
|
2011-03-02 02:12:44 +08:00
|
|
|
QualifierLoc,
|
|
|
|
T);
|
2009-09-11 12:59:25 +08:00
|
|
|
}
|
|
|
|
|
2017-01-20 08:20:39 +08:00
|
|
|
TemplateName TemplateInstantiator::TransformTemplateName(
|
|
|
|
CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
|
|
|
|
QualType ObjectType, NamedDecl *FirstQualifierInScope,
|
|
|
|
bool AllowInjectedClassName) {
|
2011-03-03 02:07:45 +08:00
|
|
|
if (TemplateTemplateParmDecl *TTP
|
|
|
|
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
|
|
|
|
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
|
|
|
|
// If the corresponding template argument is NULL or non-existent, it's
|
|
|
|
// because we are performing instantiation from explicitly-specified
|
|
|
|
// template arguments in a function template, but there were some
|
|
|
|
// arguments left unspecified.
|
|
|
|
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
|
|
|
|
TTP->getPosition()))
|
|
|
|
return Name;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-03 02:07:45 +08:00
|
|
|
TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-03 02:07:45 +08:00
|
|
|
if (TTP->isParameterPack()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(Arg.getKind() == TemplateArgument::Pack &&
|
2011-03-03 02:07:45 +08:00
|
|
|
"Missing argument pack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-03 02:07:45 +08:00
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
|
|
|
// We have the template argument pack to substitute, but we're not
|
|
|
|
// actually expanding the enclosing pack expansion yet. So, just
|
|
|
|
// keep the entire argument pack.
|
|
|
|
return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg);
|
|
|
|
}
|
2013-07-20 03:40:38 +08:00
|
|
|
|
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2011-03-03 02:07:45 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2017-08-30 06:14:43 +08:00
|
|
|
TemplateName Template = Arg.getAsTemplate().getNameToSubstitute();
|
2011-05-06 05:57:07 +08:00
|
|
|
assert(!Template.isNull() && "Null template template argument");
|
2017-08-30 06:14:43 +08:00
|
|
|
assert(!Template.getAsQualifiedTemplateName() &&
|
|
|
|
"template decl to substitute is qualified?");
|
2011-06-30 16:33:18 +08:00
|
|
|
|
|
|
|
Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template);
|
2011-03-03 02:07:45 +08:00
|
|
|
return Template;
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-03-03 02:07:45 +08:00
|
|
|
if (SubstTemplateTemplateParmPackStorage *SubstPack
|
|
|
|
= Name.getAsSubstTemplateTemplateParmPack()) {
|
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1)
|
|
|
|
return Name;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-07-20 03:40:38 +08:00
|
|
|
TemplateArgument Arg = SubstPack->getArgumentPack();
|
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2017-08-30 06:14:43 +08:00
|
|
|
return Arg.getAsTemplate().getNameToSubstitute();
|
2011-03-03 02:07:45 +08:00
|
|
|
}
|
2017-01-20 08:20:39 +08:00
|
|
|
|
|
|
|
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
|
|
|
|
FirstQualifierInScope,
|
|
|
|
AllowInjectedClassName);
|
2011-03-03 02:07:45 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
ExprResult
|
2009-12-08 17:21:05 +08:00
|
|
|
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
|
2009-09-11 09:22:35 +08:00
|
|
|
if (!E->isTypeDependent())
|
2014-05-29 22:05:12 +08:00
|
|
|
return E;
|
2009-09-11 09:22:35 +08:00
|
|
|
|
2018-10-28 03:21:19 +08:00
|
|
|
return getSema().BuildPredefinedExpr(E->getLocation(), E->getIdentKind());
|
2009-09-11 09:22:35 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2010-02-06 16:42:39 +08:00
|
|
|
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
|
2010-02-09 07:41:45 +08:00
|
|
|
NonTypeTemplateParmDecl *NTTP) {
|
2010-02-06 16:42:39 +08:00
|
|
|
// If the corresponding template argument is NULL or non-existent, it's
|
|
|
|
// because we are performing instantiation from explicitly-specified
|
|
|
|
// template arguments in a function template, but there were some
|
|
|
|
// arguments left unspecified.
|
|
|
|
if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
|
|
|
|
NTTP->getPosition()))
|
2014-05-29 22:05:12 +08:00
|
|
|
return E;
|
2009-11-01 01:21:17 +08:00
|
|
|
|
2010-12-24 08:15:10 +08:00
|
|
|
TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
|
2017-02-21 14:30:38 +08:00
|
|
|
|
|
|
|
if (TemplateArgs.getNumLevels() != TemplateArgs.getNumSubstitutedLevels()) {
|
|
|
|
// We're performing a partial substitution, so the substituted argument
|
|
|
|
// could be dependent. As a result we can't create a SubstNonType*Expr
|
|
|
|
// node now, since that represents a fully-substituted argument.
|
|
|
|
// FIXME: We should have some AST representation for this.
|
|
|
|
if (Arg.getKind() == TemplateArgument::Pack) {
|
|
|
|
// FIXME: This won't work for alias templates.
|
|
|
|
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
|
|
|
|
"unexpected pack arguments in partial substitution");
|
|
|
|
Arg = Arg.pack_begin()->getPackExpansionPattern();
|
|
|
|
}
|
|
|
|
assert(Arg.getKind() == TemplateArgument::Expression &&
|
|
|
|
"unexpected nontype template argument kind in partial substitution");
|
|
|
|
return Arg.getAsExpr();
|
|
|
|
}
|
|
|
|
|
2010-12-24 08:15:10 +08:00
|
|
|
if (NTTP->isParameterPack()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(Arg.getKind() == TemplateArgument::Pack &&
|
2010-12-24 08:15:10 +08:00
|
|
|
"Missing argument pack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-24 08:15:10 +08:00
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
2011-01-15 09:15:58 +08:00
|
|
|
// We have an argument pack, but we can't select a particular argument
|
|
|
|
// out of it yet. Therefore, we'll build an expression to hold on to that
|
|
|
|
// argument pack.
|
|
|
|
QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
|
2018-07-31 03:24:48 +08:00
|
|
|
E->getLocation(),
|
2011-01-15 09:15:58 +08:00
|
|
|
NTTP->getDeclName());
|
|
|
|
if (TargetType.isNull())
|
|
|
|
return ExprError();
|
2018-02-14 10:07:53 +08:00
|
|
|
|
|
|
|
return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(
|
|
|
|
TargetType.getNonLValueExprType(SemaRef.Context),
|
|
|
|
TargetType->isReferenceType() ? VK_LValue : VK_RValue, NTTP,
|
|
|
|
E->getLocation(), Arg);
|
2010-12-24 08:15:10 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-07-20 03:40:38 +08:00
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2010-12-24 08:15:10 +08:00
|
|
|
}
|
2009-11-01 01:21:17 +08:00
|
|
|
|
2011-07-15 13:09:51 +08:00
|
|
|
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
|
|
|
|
}
|
|
|
|
|
2014-10-13 04:46:07 +08:00
|
|
|
const LoopHintAttr *
|
|
|
|
TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
|
|
|
|
Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get();
|
|
|
|
|
|
|
|
if (TransformedExpr == LH->getValue())
|
|
|
|
return LH;
|
|
|
|
|
|
|
|
// Generate error if there is a problem with the value.
|
|
|
|
if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation()))
|
|
|
|
return LH;
|
|
|
|
|
|
|
|
// Create new LoopHintValueAttr with integral expression in place of the
|
|
|
|
// non-type template parameter.
|
2019-09-14 01:39:31 +08:00
|
|
|
return LoopHintAttr::CreateImplicit(getSema().Context, LH->getOption(),
|
|
|
|
LH->getState(), TransformedExpr, *LH);
|
2014-10-13 04:46:07 +08:00
|
|
|
}
|
|
|
|
|
2011-07-15 13:09:51 +08:00
|
|
|
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
|
|
|
|
NonTypeTemplateParmDecl *parm,
|
|
|
|
SourceLocation loc,
|
2012-07-09 11:07:20 +08:00
|
|
|
TemplateArgument arg) {
|
2011-07-15 13:09:51 +08:00
|
|
|
ExprResult result;
|
|
|
|
QualType type;
|
|
|
|
|
2010-02-06 16:42:39 +08:00
|
|
|
// The template argument itself might be an expression, in which
|
|
|
|
// case we just return that expression.
|
2011-07-15 13:09:51 +08:00
|
|
|
if (arg.getKind() == TemplateArgument::Expression) {
|
|
|
|
Expr *argExpr = arg.getAsExpr();
|
2014-05-29 22:05:12 +08:00
|
|
|
result = argExpr;
|
2011-07-15 13:09:51 +08:00
|
|
|
type = argExpr->getType();
|
2009-11-01 01:21:17 +08:00
|
|
|
|
2012-09-26 10:36:12 +08:00
|
|
|
} else if (arg.getKind() == TemplateArgument::Declaration ||
|
|
|
|
arg.getKind() == TemplateArgument::NullPtr) {
|
2012-04-07 06:40:38 +08:00
|
|
|
ValueDecl *VD;
|
2012-09-26 10:36:12 +08:00
|
|
|
if (arg.getKind() == TemplateArgument::Declaration) {
|
2018-03-01 13:43:23 +08:00
|
|
|
VD = arg.getAsDecl();
|
2012-04-07 06:40:38 +08:00
|
|
|
|
|
|
|
// Find the instantiation of the template argument. This is
|
|
|
|
// required for nested templates.
|
|
|
|
VD = cast_or_null<ValueDecl>(
|
|
|
|
getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
|
|
|
|
if (!VD)
|
|
|
|
return ExprError();
|
|
|
|
} else {
|
|
|
|
// Propagate NULL template argument.
|
2014-05-26 14:22:03 +08:00
|
|
|
VD = nullptr;
|
2012-04-07 06:40:38 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-02-06 18:23:53 +08:00
|
|
|
// Derive the type we want the substituted decl to have. This had
|
|
|
|
// better be non-dependent, or these checks will have serious problems.
|
2011-07-15 13:09:51 +08:00
|
|
|
if (parm->isExpandedParameterPack()) {
|
|
|
|
type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
|
2018-07-31 03:24:48 +08:00
|
|
|
} else if (parm->isParameterPack() &&
|
2011-07-15 13:09:51 +08:00
|
|
|
isa<PackExpansionType>(parm->getType())) {
|
|
|
|
type = SemaRef.SubstType(
|
|
|
|
cast<PackExpansionType>(parm->getType())->getPattern(),
|
|
|
|
TemplateArgs, loc, parm->getDeclName());
|
|
|
|
} else {
|
2016-09-29 07:55:27 +08:00
|
|
|
type = SemaRef.SubstType(VD ? arg.getParamTypeForDecl() : arg.getNullPtrType(),
|
|
|
|
TemplateArgs, loc, parm->getDeclName());
|
2011-07-15 13:09:51 +08:00
|
|
|
}
|
|
|
|
assert(!type.isNull() && "type substitution failed for param type");
|
|
|
|
assert(!type->isDependentType() && "param type still dependent");
|
|
|
|
result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, type, loc);
|
|
|
|
|
|
|
|
if (!result.isInvalid()) type = result.get()->getType();
|
|
|
|
} else {
|
|
|
|
result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
|
|
|
|
|
|
|
|
// Note that this type can be different from the type of 'result',
|
|
|
|
// e.g. if it's an enum type.
|
|
|
|
type = arg.getIntegralType();
|
2010-02-06 16:42:39 +08:00
|
|
|
}
|
2011-07-15 13:09:51 +08:00
|
|
|
if (result.isInvalid()) return ExprError();
|
2010-02-06 16:42:39 +08:00
|
|
|
|
2014-05-29 18:55:11 +08:00
|
|
|
Expr *resultExpr = result.get();
|
2014-05-29 22:05:12 +08:00
|
|
|
return new (SemaRef.Context) SubstNonTypeTemplateParmExpr(
|
|
|
|
type, resultExpr->getValueKind(), loc, parm, resultExpr);
|
2010-02-06 16:42:39 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
ExprResult
|
2011-01-15 09:15:58 +08:00
|
|
|
TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
|
|
|
|
SubstNonTypeTemplateParmPackExpr *E) {
|
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
|
|
|
// We aren't expanding the parameter pack, so just return ourselves.
|
2014-05-29 22:05:12 +08:00
|
|
|
return E;
|
2011-01-15 09:15:58 +08:00
|
|
|
}
|
2013-07-20 03:40:38 +08:00
|
|
|
|
|
|
|
TemplateArgument Arg = E->getArgumentPack();
|
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2011-07-15 13:09:51 +08:00
|
|
|
return transformNonTypeTemplateParmRef(E->getParameterPack(),
|
|
|
|
E->getParameterPackLocation(),
|
|
|
|
Arg);
|
2011-01-15 09:15:58 +08:00
|
|
|
}
|
2010-02-06 16:42:39 +08:00
|
|
|
|
2020-01-31 21:55:06 +08:00
|
|
|
ExprResult
|
|
|
|
TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
|
|
|
|
SubstNonTypeTemplateParmExpr *E) {
|
|
|
|
ExprResult SubstReplacement = TransformExpr(E->getReplacement());
|
|
|
|
if (SubstReplacement.isInvalid())
|
|
|
|
return true;
|
|
|
|
QualType SubstType = TransformType(E->getType());
|
|
|
|
if (SubstType.isNull())
|
|
|
|
return true;
|
|
|
|
// The type may have been previously dependent and not now, which means we
|
|
|
|
// might have to implicit cast the argument to the new type, for example:
|
|
|
|
// template<auto T, decltype(T) U>
|
|
|
|
// concept C = sizeof(U) == 4;
|
|
|
|
// void foo() requires C<2, 'a'> { }
|
|
|
|
// When normalizing foo(), we first form the normalized constraints of C:
|
|
|
|
// AtomicExpr(sizeof(U) == 4,
|
|
|
|
// U=SubstNonTypeTemplateParmExpr(Param=U,
|
|
|
|
// Expr=DeclRef(U),
|
|
|
|
// Type=decltype(T)))
|
|
|
|
// Then we substitute T = 2, U = 'a' into the parameter mapping, and need to
|
|
|
|
// produce:
|
|
|
|
// AtomicExpr(sizeof(U) == 4,
|
|
|
|
// U=SubstNonTypeTemplateParmExpr(Param=U,
|
|
|
|
// Expr=ImpCast(
|
|
|
|
// decltype(2),
|
|
|
|
// SubstNTTPE(Param=U, Expr='a',
|
|
|
|
// Type=char)),
|
|
|
|
// Type=decltype(2)))
|
|
|
|
// The call to CheckTemplateArgument here produces the ImpCast.
|
|
|
|
TemplateArgument Converted;
|
|
|
|
if (SemaRef.CheckTemplateArgument(E->getParameter(), SubstType,
|
|
|
|
SubstReplacement.get(),
|
|
|
|
Converted).isInvalid())
|
|
|
|
return true;
|
|
|
|
return transformNonTypeTemplateParmRef(E->getParameter(),
|
|
|
|
E->getExprLoc(), Converted);
|
|
|
|
}
|
|
|
|
|
2019-05-22 04:10:50 +08:00
|
|
|
ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
|
|
|
|
SourceLocation Loc) {
|
2012-09-12 08:56:43 +08:00
|
|
|
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
|
|
|
|
return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult
|
|
|
|
TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
|
|
|
if (getSema().ArgumentPackSubstitutionIndex != -1) {
|
|
|
|
// We can expand this parameter pack now.
|
2019-05-22 04:10:50 +08:00
|
|
|
VarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
|
|
|
|
VarDecl *VD = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), D));
|
2012-09-12 08:56:43 +08:00
|
|
|
if (!VD)
|
|
|
|
return ExprError();
|
2019-05-22 04:10:50 +08:00
|
|
|
return RebuildVarDeclRefExpr(VD, E->getExprLoc());
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QualType T = TransformType(E->getType());
|
|
|
|
if (T.isNull())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
// Transform each of the parameter expansions into the corresponding
|
|
|
|
// parameters in the instantiation of the function decl.
|
2019-05-22 04:10:50 +08:00
|
|
|
SmallVector<VarDecl *, 8> Vars;
|
|
|
|
Vars.reserve(E->getNumExpansions());
|
2012-09-12 08:56:43 +08:00
|
|
|
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
|
|
|
|
I != End; ++I) {
|
2019-05-22 04:10:50 +08:00
|
|
|
VarDecl *D = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), *I));
|
2012-09-12 08:56:43 +08:00
|
|
|
if (!D)
|
|
|
|
return ExprError();
|
2019-05-22 04:10:50 +08:00
|
|
|
Vars.push_back(D);
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
2019-06-05 01:17:20 +08:00
|
|
|
auto *PackExpr =
|
|
|
|
FunctionParmPackExpr::Create(getSema().Context, T, E->getParameterPack(),
|
|
|
|
E->getParameterPackLocation(), Vars);
|
|
|
|
getSema().MarkFunctionParmPackReferenced(PackExpr);
|
|
|
|
return PackExpr;
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult
|
|
|
|
TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
|
2019-05-22 04:10:50 +08:00
|
|
|
VarDecl *PD) {
|
2012-09-12 08:56:43 +08:00
|
|
|
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
|
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
|
|
|
|
= getSema().CurrentInstantiationScope->findInstantiationOf(PD);
|
|
|
|
assert(Found && "no instantiation for parameter pack");
|
|
|
|
|
|
|
|
Decl *TransformedDecl;
|
|
|
|
if (DeclArgumentPack *Pack = Found->dyn_cast<DeclArgumentPack *>()) {
|
2014-07-28 08:02:09 +08:00
|
|
|
// If this is a reference to a function parameter pack which we can
|
|
|
|
// substitute but can't yet expand, build a FunctionParmPackExpr for it.
|
2012-09-12 08:56:43 +08:00
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
|
|
|
QualType T = TransformType(E->getType());
|
|
|
|
if (T.isNull())
|
|
|
|
return ExprError();
|
2019-06-05 01:17:20 +08:00
|
|
|
auto *PackExpr = FunctionParmPackExpr::Create(getSema().Context, T, PD,
|
|
|
|
E->getExprLoc(), *Pack);
|
|
|
|
getSema().MarkFunctionParmPackReferenced(PackExpr);
|
|
|
|
return PackExpr;
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex];
|
|
|
|
} else {
|
|
|
|
TransformedDecl = Found->get<Decl*>();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have either an unexpanded pack or a specific expansion.
|
2019-05-22 04:10:50 +08:00
|
|
|
return RebuildVarDeclRefExpr(cast<VarDecl>(TransformedDecl), E->getExprLoc());
|
2012-09-12 08:56:43 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2010-02-06 16:42:39 +08:00
|
|
|
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
|
|
|
|
NamedDecl *D = E->getDecl();
|
2012-09-12 08:56:43 +08:00
|
|
|
|
|
|
|
// Handle references to non-type template parameters and non-type template
|
|
|
|
// parameter packs.
|
2010-02-06 16:42:39 +08:00
|
|
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
|
|
|
if (NTTP->getDepth() < TemplateArgs.getNumLevels())
|
|
|
|
return TransformTemplateParmRefExpr(E, NTTP);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-11-01 01:21:17 +08:00
|
|
|
// We have a non-type template parameter that isn't fully substituted;
|
|
|
|
// FindInstantiatedDecl will find it in the local instantiation scope.
|
2009-08-11 13:31:07 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-09-12 08:56:43 +08:00
|
|
|
// Handle references to function parameter packs.
|
2019-05-22 04:10:50 +08:00
|
|
|
if (VarDecl *PD = dyn_cast<VarDecl>(D))
|
2012-09-12 08:56:43 +08:00
|
|
|
if (PD->isParameterPack())
|
|
|
|
return TransformFunctionParmPackRefExpr(E, PD);
|
|
|
|
|
2009-12-08 17:21:05 +08:00
|
|
|
return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
|
2009-08-11 13:31:07 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
|
2009-12-08 17:21:05 +08:00
|
|
|
CXXDefaultArgExpr *E) {
|
2009-11-08 21:56:19 +08:00
|
|
|
assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
|
|
|
|
getDescribedFunctionTemplate() &&
|
|
|
|
"Default arg expressions are never formed in dependent cases.");
|
2009-12-24 07:03:06 +08:00
|
|
|
return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(),
|
2018-07-31 03:24:48 +08:00
|
|
|
cast<FunctionDecl>(E->getParam()->getDeclContext()),
|
2009-12-24 07:03:06 +08:00
|
|
|
E->getParam());
|
2009-11-08 21:56:19 +08:00
|
|
|
}
|
|
|
|
|
2014-11-12 10:00:47 +08:00
|
|
|
template<typename Fn>
|
2012-04-16 15:05:22 +08:00
|
|
|
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
|
|
|
|
FunctionProtoTypeLoc TL,
|
|
|
|
CXXRecordDecl *ThisContext,
|
2018-12-13 18:15:27 +08:00
|
|
|
Qualifiers ThisTypeQuals,
|
2014-11-12 10:00:47 +08:00
|
|
|
Fn TransformExceptionSpec) {
|
2012-04-16 15:05:22 +08:00
|
|
|
// We need a local instantiation scope for this function prototype.
|
|
|
|
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
|
2014-11-12 10:00:47 +08:00
|
|
|
return inherited::TransformFunctionProtoType(
|
|
|
|
TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
|
2012-04-16 15:05:22 +08:00
|
|
|
}
|
|
|
|
|
2010-03-11 17:03:00 +08:00
|
|
|
ParmVarDecl *
|
2011-01-15 06:40:04 +08:00
|
|
|
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
|
2011-05-02 06:35:37 +08:00
|
|
|
int indexAdjustment,
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<unsigned> NumExpansions,
|
2012-01-26 00:15:54 +08:00
|
|
|
bool ExpectParameterPack) {
|
2019-11-27 19:03:11 +08:00
|
|
|
auto NewParm =
|
|
|
|
SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
|
|
|
|
NumExpansions, ExpectParameterPack);
|
|
|
|
if (NewParm && SemaRef.getLangOpts().OpenCL)
|
|
|
|
SemaRef.deduceOpenCLAddressSpace(NewParm);
|
|
|
|
return NewParm;
|
2010-03-11 17:03:00 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType
|
2009-10-21 08:40:46 +08:00
|
|
|
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
2010-11-12 16:19:04 +08:00
|
|
|
TemplateTypeParmTypeLoc TL) {
|
2011-01-19 14:33:43 +08:00
|
|
|
const TemplateTypeParmType *T = TL.getTypePtr();
|
2009-08-29 04:31:08 +08:00
|
|
|
if (T->getDepth() < TemplateArgs.getNumLevels()) {
|
2009-02-28 03:31:52 +08:00
|
|
|
// Replace the template type parameter with its corresponding
|
|
|
|
// template argument.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// If the corresponding template argument is NULL or doesn't exist, it's
|
|
|
|
// because we are performing instantiation from explicitly-specified
|
|
|
|
// template arguments in a function template class, but there were some
|
2009-07-01 08:28:38 +08:00
|
|
|
// arguments left unspecified.
|
2009-10-21 08:40:46 +08:00
|
|
|
if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) {
|
|
|
|
TemplateTypeParmTypeLoc NewTL
|
|
|
|
= TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
|
|
|
|
NewTL.setNameLoc(TL.getNameLoc());
|
|
|
|
return TL.getType();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-12-21 06:05:00 +08:00
|
|
|
TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-21 06:05:00 +08:00
|
|
|
if (T->isParameterPack()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
assert(Arg.getKind() == TemplateArgument::Pack &&
|
2010-12-21 06:05:00 +08:00
|
|
|
"Missing argument pack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-21 06:05:00 +08:00
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
2011-01-14 10:55:32 +08:00
|
|
|
// We have the template argument pack, but we're not expanding the
|
|
|
|
// enclosing pack expansion yet. Just save the template argument
|
|
|
|
// pack for later substitution.
|
|
|
|
QualType Result
|
|
|
|
= getSema().Context.getSubstTemplateTypeParmPackType(T, Arg);
|
|
|
|
SubstTemplateTypeParmPackTypeLoc NewTL
|
|
|
|
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
|
|
|
|
NewTL.setNameLoc(TL.getNameLoc());
|
|
|
|
return Result;
|
2010-12-21 06:05:00 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-07-20 03:40:38 +08:00
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
2010-12-21 06:05:00 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-21 06:05:00 +08:00
|
|
|
assert(Arg.getKind() == TemplateArgument::Type &&
|
2009-02-28 03:31:52 +08:00
|
|
|
"Template argument kind mismatch");
|
2009-08-29 04:31:08 +08:00
|
|
|
|
2010-12-21 06:05:00 +08:00
|
|
|
QualType Replacement = Arg.getAsType();
|
2009-10-18 17:09:24 +08:00
|
|
|
|
|
|
|
// TODO: only do this uniquing once, at the start of instantiation.
|
2009-10-21 08:40:46 +08:00
|
|
|
QualType Result
|
|
|
|
= getSema().Context.getSubstTemplateTypeParmType(T, Replacement);
|
|
|
|
SubstTemplateTypeParmTypeLoc NewTL
|
|
|
|
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
|
|
|
|
NewTL.setNameLoc(TL.getNameLoc());
|
|
|
|
return Result;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
|
|
|
// The template type parameter comes from an inner template (e.g.,
|
|
|
|
// the template parameter list of a member template inside the
|
|
|
|
// template we are instantiating). Create a new template type
|
|
|
|
// parameter with the template "level" reduced by one.
|
2014-05-26 14:22:03 +08:00
|
|
|
TemplateTypeParmDecl *NewTTPDecl = nullptr;
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
|
|
|
|
NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
|
|
|
|
TransformDecl(TL.getNameLoc(), OldTTPDecl));
|
|
|
|
|
2017-02-21 14:30:38 +08:00
|
|
|
QualType Result = getSema().Context.getTemplateTypeParmType(
|
|
|
|
T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(),
|
|
|
|
T->isParameterPack(), NewTTPDecl);
|
2009-10-21 08:40:46 +08:00
|
|
|
TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
|
|
|
|
NewTL.setNameLoc(TL.getNameLoc());
|
|
|
|
return Result;
|
2011-01-14 10:55:32 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
QualType
|
2011-01-14 10:55:32 +08:00
|
|
|
TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
|
|
|
|
TypeLocBuilder &TLB,
|
|
|
|
SubstTemplateTypeParmPackTypeLoc TL) {
|
|
|
|
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
|
|
|
// We aren't expanding the parameter pack, so just return ourselves.
|
|
|
|
SubstTemplateTypeParmPackTypeLoc NewTL
|
|
|
|
= TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType());
|
|
|
|
NewTL.setNameLoc(TL.getNameLoc());
|
|
|
|
return TL.getType();
|
|
|
|
}
|
2013-07-20 03:40:38 +08:00
|
|
|
|
|
|
|
TemplateArgument Arg = TL.getTypePtr()->getArgumentPack();
|
|
|
|
Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
|
|
|
|
QualType Result = Arg.getAsType();
|
|
|
|
|
2011-01-14 10:55:32 +08:00
|
|
|
Result = getSema().Context.getSubstTemplateTypeParmType(
|
|
|
|
TL.getTypePtr()->getReplacedParameter(),
|
|
|
|
Result);
|
|
|
|
SubstTemplateTypeParmTypeLoc NewTL
|
|
|
|
= TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
|
|
|
|
NewTL.setNameLoc(TL.getNameLoc());
|
|
|
|
return Result;
|
2009-02-28 08:25:32 +08:00
|
|
|
}
|
2009-02-28 03:31:52 +08:00
|
|
|
|
2020-01-18 15:11:43 +08:00
|
|
|
template<typename EntityPrinter>
|
|
|
|
static concepts::Requirement::SubstitutionDiagnostic *
|
|
|
|
createSubstDiag(Sema &S, TemplateDeductionInfo &Info, EntityPrinter Printer) {
|
|
|
|
SmallString<128> Message;
|
|
|
|
SourceLocation ErrorLoc;
|
|
|
|
if (Info.hasSFINAEDiagnostic()) {
|
|
|
|
PartialDiagnosticAt PDA(SourceLocation(),
|
|
|
|
PartialDiagnostic::NullDiagnostic{});
|
|
|
|
Info.takeSFINAEDiagnostic(PDA);
|
|
|
|
PDA.second.EmitToString(S.getDiagnostics(), Message);
|
|
|
|
ErrorLoc = PDA.first;
|
|
|
|
} else {
|
|
|
|
ErrorLoc = Info.getLocation();
|
|
|
|
}
|
|
|
|
char *MessageBuf = new (S.Context) char[Message.size()];
|
|
|
|
std::copy(Message.begin(), Message.end(), MessageBuf);
|
|
|
|
SmallString<128> Entity;
|
|
|
|
llvm::raw_svector_ostream OS(Entity);
|
|
|
|
Printer(OS);
|
|
|
|
char *EntityBuf = new (S.Context) char[Entity.size()];
|
|
|
|
std::copy(Entity.begin(), Entity.end(), EntityBuf);
|
|
|
|
return new (S.Context) concepts::Requirement::SubstitutionDiagnostic{
|
|
|
|
StringRef(EntityBuf, Entity.size()), ErrorLoc,
|
|
|
|
StringRef(MessageBuf, Message.size())};
|
|
|
|
}
|
|
|
|
|
|
|
|
concepts::TypeRequirement *
|
|
|
|
TemplateInstantiator::TransformTypeRequirement(concepts::TypeRequirement *Req) {
|
|
|
|
if (!Req->isDependent() && !AlwaysRebuild())
|
|
|
|
return Req;
|
|
|
|
if (Req->isSubstitutionFailure()) {
|
|
|
|
if (AlwaysRebuild())
|
|
|
|
return RebuildTypeRequirement(
|
|
|
|
Req->getSubstitutionDiagnostic());
|
|
|
|
return Req;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sema::SFINAETrap Trap(SemaRef);
|
|
|
|
TemplateDeductionInfo Info(Req->getType()->getTypeLoc().getBeginLoc());
|
|
|
|
Sema::InstantiatingTemplate TypeInst(SemaRef,
|
|
|
|
Req->getType()->getTypeLoc().getBeginLoc(), Req, Info,
|
|
|
|
Req->getType()->getTypeLoc().getSourceRange());
|
|
|
|
if (TypeInst.isInvalid())
|
|
|
|
return nullptr;
|
|
|
|
TypeSourceInfo *TransType = TransformType(Req->getType());
|
|
|
|
if (!TransType || Trap.hasErrorOccurred())
|
|
|
|
return RebuildTypeRequirement(createSubstDiag(SemaRef, Info,
|
|
|
|
[&] (llvm::raw_ostream& OS) {
|
|
|
|
Req->getType()->getType().print(OS, SemaRef.getPrintingPolicy());
|
|
|
|
}));
|
|
|
|
return RebuildTypeRequirement(TransType);
|
|
|
|
}
|
|
|
|
|
|
|
|
concepts::ExprRequirement *
|
|
|
|
TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) {
|
|
|
|
if (!Req->isDependent() && !AlwaysRebuild())
|
|
|
|
return Req;
|
|
|
|
|
|
|
|
Sema::SFINAETrap Trap(SemaRef);
|
|
|
|
TemplateDeductionInfo Info(Req->getExpr()->getBeginLoc());
|
|
|
|
|
|
|
|
llvm::PointerUnion<Expr *, concepts::Requirement::SubstitutionDiagnostic *>
|
|
|
|
TransExpr;
|
|
|
|
if (Req->isExprSubstitutionFailure())
|
|
|
|
TransExpr = Req->getExprSubstitutionDiagnostic();
|
|
|
|
else {
|
|
|
|
Sema::InstantiatingTemplate ExprInst(SemaRef, Req->getExpr()->getBeginLoc(),
|
|
|
|
Req, Info,
|
|
|
|
Req->getExpr()->getSourceRange());
|
|
|
|
if (ExprInst.isInvalid())
|
|
|
|
return nullptr;
|
|
|
|
ExprResult TransExprRes = TransformExpr(Req->getExpr());
|
|
|
|
if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
|
|
|
|
TransExpr = createSubstDiag(SemaRef, Info,
|
|
|
|
[&] (llvm::raw_ostream& OS) {
|
|
|
|
Req->getExpr()->printPretty(OS, nullptr,
|
|
|
|
SemaRef.getPrintingPolicy());
|
|
|
|
});
|
|
|
|
else
|
|
|
|
TransExpr = TransExprRes.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Optional<concepts::ExprRequirement::ReturnTypeRequirement> TransRetReq;
|
|
|
|
const auto &RetReq = Req->getReturnTypeRequirement();
|
|
|
|
if (RetReq.isEmpty())
|
|
|
|
TransRetReq.emplace();
|
|
|
|
else if (RetReq.isSubstitutionFailure())
|
|
|
|
TransRetReq.emplace(RetReq.getSubstitutionDiagnostic());
|
|
|
|
else if (RetReq.isTypeConstraint()) {
|
|
|
|
TemplateParameterList *OrigTPL =
|
|
|
|
RetReq.getTypeConstraintTemplateParameterList();
|
|
|
|
Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(),
|
|
|
|
Req, Info, OrigTPL->getSourceRange());
|
|
|
|
if (TPLInst.isInvalid())
|
|
|
|
return nullptr;
|
|
|
|
TemplateParameterList *TPL =
|
|
|
|
TransformTemplateParameterList(OrigTPL);
|
|
|
|
if (!TPL)
|
|
|
|
TransRetReq.emplace(createSubstDiag(SemaRef, Info,
|
|
|
|
[&] (llvm::raw_ostream& OS) {
|
|
|
|
RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint()
|
|
|
|
->printPretty(OS, nullptr, SemaRef.getPrintingPolicy());
|
|
|
|
}));
|
|
|
|
else {
|
|
|
|
TPLInst.Clear();
|
|
|
|
TransRetReq.emplace(TPL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(TransRetReq.hasValue() &&
|
|
|
|
"All code paths leading here must set TransRetReq");
|
|
|
|
if (Expr *E = TransExpr.dyn_cast<Expr *>())
|
|
|
|
return RebuildExprRequirement(E, Req->isSimple(), Req->getNoexceptLoc(),
|
|
|
|
std::move(*TransRetReq));
|
|
|
|
return RebuildExprRequirement(
|
|
|
|
TransExpr.get<concepts::Requirement::SubstitutionDiagnostic *>(),
|
|
|
|
Req->isSimple(), Req->getNoexceptLoc(), std::move(*TransRetReq));
|
|
|
|
}
|
|
|
|
|
|
|
|
concepts::NestedRequirement *
|
|
|
|
TemplateInstantiator::TransformNestedRequirement(
|
|
|
|
concepts::NestedRequirement *Req) {
|
|
|
|
if (!Req->isDependent() && !AlwaysRebuild())
|
|
|
|
return Req;
|
|
|
|
if (Req->isSubstitutionFailure()) {
|
|
|
|
if (AlwaysRebuild())
|
|
|
|
return RebuildNestedRequirement(
|
|
|
|
Req->getSubstitutionDiagnostic());
|
|
|
|
return Req;
|
|
|
|
}
|
|
|
|
Sema::InstantiatingTemplate ReqInst(SemaRef,
|
|
|
|
Req->getConstraintExpr()->getBeginLoc(), Req,
|
|
|
|
Sema::InstantiatingTemplate::ConstraintsCheck{},
|
|
|
|
Req->getConstraintExpr()->getSourceRange());
|
|
|
|
|
|
|
|
ExprResult TransConstraint;
|
|
|
|
TemplateDeductionInfo Info(Req->getConstraintExpr()->getBeginLoc());
|
|
|
|
{
|
|
|
|
EnterExpressionEvaluationContext ContextRAII(
|
|
|
|
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
|
|
|
Sema::SFINAETrap Trap(SemaRef);
|
|
|
|
Sema::InstantiatingTemplate ConstrInst(SemaRef,
|
|
|
|
Req->getConstraintExpr()->getBeginLoc(), Req, Info,
|
|
|
|
Req->getConstraintExpr()->getSourceRange());
|
|
|
|
if (ConstrInst.isInvalid())
|
|
|
|
return nullptr;
|
|
|
|
TransConstraint = TransformExpr(Req->getConstraintExpr());
|
|
|
|
if (TransConstraint.isInvalid() || Trap.hasErrorOccurred())
|
|
|
|
return RebuildNestedRequirement(createSubstDiag(SemaRef, Info,
|
|
|
|
[&] (llvm::raw_ostream& OS) {
|
|
|
|
Req->getConstraintExpr()->printPretty(OS, nullptr,
|
|
|
|
SemaRef.getPrintingPolicy());
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
return RebuildNestedRequirement(TransConstraint.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Perform substitution on the type T with a given set of template
|
2009-08-26 06:02:44 +08:00
|
|
|
/// arguments.
|
2009-02-28 03:31:52 +08:00
|
|
|
///
|
|
|
|
/// This routine substitutes the given template arguments into the
|
|
|
|
/// type T and produces the instantiated type.
|
|
|
|
///
|
|
|
|
/// \param T the type into which the template arguments will be
|
|
|
|
/// substituted. If this type is not dependent, it will be returned
|
|
|
|
/// immediately.
|
|
|
|
///
|
2012-06-15 05:40:34 +08:00
|
|
|
/// \param Args the template arguments that will be
|
2009-02-28 03:31:52 +08:00
|
|
|
/// substituted for the top-level template parameters within T.
|
|
|
|
///
|
|
|
|
/// \param Loc the location in the source code where this substitution
|
|
|
|
/// is being performed. It will typically be the location of the
|
|
|
|
/// declarator (if we're instantiating the type of some declaration)
|
|
|
|
/// or the location of the type in the source code (if, e.g., we're
|
|
|
|
/// instantiating the type of a cast expression).
|
|
|
|
///
|
|
|
|
/// \param Entity the name of the entity associated with a declaration
|
|
|
|
/// being instantiated (if any). May be empty to indicate that there
|
|
|
|
/// is no such entity (if, e.g., this is a type that occurs as part of
|
|
|
|
/// a cast expression) or that the entity has no name (e.g., an
|
|
|
|
/// unnamed function parameter).
|
|
|
|
///
|
2017-01-31 04:39:26 +08:00
|
|
|
/// \param AllowDeducedTST Whether a DeducedTemplateSpecializationType is
|
|
|
|
/// acceptable as the top level type of the result.
|
|
|
|
///
|
2009-02-28 03:31:52 +08:00
|
|
|
/// \returns If the instantiation succeeds, the instantiated
|
|
|
|
/// type. Otherwise, produces diagnostics and returns a NULL type.
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T,
|
2009-10-21 08:58:09 +08:00
|
|
|
const MultiLevelTemplateArgumentList &Args,
|
|
|
|
SourceLocation Loc,
|
2017-01-31 04:39:26 +08:00
|
|
|
DeclarationName Entity,
|
|
|
|
bool AllowDeducedTST) {
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty() &&
|
2009-10-21 08:58:09 +08:00
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
if (!T->getType()->isInstantiationDependentType() &&
|
2010-05-25 01:22:01 +08:00
|
|
|
!T->getType()->isVariablyModifiedType())
|
2009-10-21 08:58:09 +08:00
|
|
|
return T;
|
|
|
|
|
|
|
|
TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
|
2017-01-31 04:39:26 +08:00
|
|
|
return AllowDeducedTST ? Instantiator.TransformTypeWithDeducedTST(T)
|
|
|
|
: Instantiator.TransformType(T);
|
2009-10-21 08:58:09 +08:00
|
|
|
}
|
|
|
|
|
2011-01-06 07:12:31 +08:00
|
|
|
TypeSourceInfo *Sema::SubstType(TypeLoc TL,
|
|
|
|
const MultiLevelTemplateArgumentList &Args,
|
|
|
|
SourceLocation Loc,
|
|
|
|
DeclarationName Entity) {
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty() &&
|
2011-01-06 07:12:31 +08:00
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-06 07:12:31 +08:00
|
|
|
if (TL.getType().isNull())
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2011-01-06 07:12:31 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
if (!TL.getType()->isInstantiationDependentType() &&
|
2011-01-06 07:12:31 +08:00
|
|
|
!TL.getType()->isVariablyModifiedType()) {
|
|
|
|
// FIXME: Make a copy of the TypeLoc data here, so that we can
|
|
|
|
// return a new TypeSourceInfo. Inefficient!
|
|
|
|
TypeLocBuilder TLB;
|
|
|
|
TLB.pushFullCopy(TL);
|
|
|
|
return TLB.getTypeSourceInfo(Context, TL.getType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
|
|
|
|
TypeLocBuilder TLB;
|
|
|
|
TLB.reserve(TL.getFullDataSize());
|
|
|
|
QualType Result = Instantiator.TransformType(TLB, TL);
|
|
|
|
if (Result.isNull())
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2011-01-06 07:12:31 +08:00
|
|
|
|
|
|
|
return TLB.getTypeSourceInfo(Context, Result);
|
|
|
|
}
|
|
|
|
|
2009-10-21 08:58:09 +08:00
|
|
|
/// Deprecated form of the above.
|
2009-09-09 23:08:12 +08:00
|
|
|
QualType Sema::SubstType(QualType T,
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
2009-08-26 06:02:44 +08:00
|
|
|
SourceLocation Loc, DeclarationName Entity) {
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty() &&
|
2009-03-11 04:44:00 +08:00
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
|
|
|
|
2010-05-25 01:22:01 +08:00
|
|
|
// If T is not a dependent type or a variably-modified type, there
|
|
|
|
// is nothing to do.
|
2011-07-01 09:22:09 +08:00
|
|
|
if (!T->isInstantiationDependentType() && !T->isVariablyModifiedType())
|
2009-02-28 03:31:52 +08:00
|
|
|
return T;
|
|
|
|
|
2009-08-05 00:50:30 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity);
|
|
|
|
return Instantiator.TransformType(T);
|
2009-02-28 03:31:52 +08:00
|
|
|
}
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2010-04-10 01:38:44 +08:00
|
|
|
static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
|
2016-02-02 06:31:51 +08:00
|
|
|
if (T->getType()->isInstantiationDependentType() ||
|
2011-07-01 09:22:09 +08:00
|
|
|
T->getType()->isVariablyModifiedType())
|
2010-04-10 01:38:44 +08:00
|
|
|
return true;
|
|
|
|
|
2010-12-15 06:11:44 +08:00
|
|
|
TypeLoc TL = T->getTypeLoc().IgnoreParens();
|
2013-02-19 06:06:02 +08:00
|
|
|
if (!TL.getAs<FunctionProtoTypeLoc>())
|
2010-04-10 01:38:44 +08:00
|
|
|
return false;
|
|
|
|
|
2013-02-19 06:06:02 +08:00
|
|
|
FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
|
2016-02-02 06:31:51 +08:00
|
|
|
for (ParmVarDecl *P : FP.getParams()) {
|
2013-08-01 05:00:18 +08:00
|
|
|
// This must be synthesized from a typedef.
|
|
|
|
if (!P) continue;
|
|
|
|
|
2016-02-02 06:31:51 +08:00
|
|
|
// If there are any parameters, a new TypeSourceInfo that refers to the
|
|
|
|
// instantiated parameters must be built.
|
|
|
|
return true;
|
2010-04-10 01:38:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A form of SubstType intended specifically for instantiating the
|
|
|
|
/// type of a FunctionDecl. Its purpose is solely to force the
|
2014-11-12 10:00:47 +08:00
|
|
|
/// instantiation of default-argument expressions and to avoid
|
|
|
|
/// instantiating an exception-specification.
|
2010-04-10 01:38:44 +08:00
|
|
|
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
|
|
|
|
const MultiLevelTemplateArgumentList &Args,
|
|
|
|
SourceLocation Loc,
|
2012-04-16 15:05:22 +08:00
|
|
|
DeclarationName Entity,
|
|
|
|
CXXRecordDecl *ThisContext,
|
2018-12-13 18:15:27 +08:00
|
|
|
Qualifiers ThisTypeQuals) {
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty() &&
|
2010-04-10 01:38:44 +08:00
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
2016-02-02 06:31:51 +08:00
|
|
|
|
2010-04-10 01:38:44 +08:00
|
|
|
if (!NeedsInstantiationAsFunctionType(T))
|
|
|
|
return T;
|
|
|
|
|
|
|
|
TemplateInstantiator Instantiator(*this, Args, Loc, Entity);
|
|
|
|
|
|
|
|
TypeLocBuilder TLB;
|
|
|
|
|
|
|
|
TypeLoc TL = T->getTypeLoc();
|
|
|
|
TLB.reserve(TL.getFullDataSize());
|
|
|
|
|
2012-04-16 15:05:22 +08:00
|
|
|
QualType Result;
|
2013-02-19 06:06:02 +08:00
|
|
|
|
2014-11-12 10:00:47 +08:00
|
|
|
if (FunctionProtoTypeLoc Proto =
|
|
|
|
TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
|
|
|
|
// Instantiate the type, other than its exception specification. The
|
|
|
|
// exception specification is instantiated in InitFunctionInstantiation
|
|
|
|
// once we've built the FunctionDecl.
|
|
|
|
// FIXME: Set the exception specification to EST_Uninstantiated here,
|
|
|
|
// instead of rebuilding the function type again later.
|
|
|
|
Result = Instantiator.TransformFunctionProtoType(
|
|
|
|
TLB, Proto, ThisContext, ThisTypeQuals,
|
|
|
|
[](FunctionProtoType::ExceptionSpecInfo &ESI,
|
|
|
|
bool &Changed) { return false; });
|
2012-04-16 15:05:22 +08:00
|
|
|
} else {
|
|
|
|
Result = Instantiator.TransformType(TLB, TL);
|
|
|
|
}
|
2010-04-10 01:38:44 +08:00
|
|
|
if (Result.isNull())
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2010-04-10 01:38:44 +08:00
|
|
|
|
|
|
|
return TLB.getTypeSourceInfo(Context, Result);
|
|
|
|
}
|
|
|
|
|
2017-06-08 05:46:22 +08:00
|
|
|
bool Sema::SubstExceptionSpec(SourceLocation Loc,
|
|
|
|
FunctionProtoType::ExceptionSpecInfo &ESI,
|
|
|
|
SmallVectorImpl<QualType> &ExceptionStorage,
|
|
|
|
const MultiLevelTemplateArgumentList &Args) {
|
|
|
|
assert(ESI.Type != EST_Uninstantiated);
|
|
|
|
|
|
|
|
bool Changed = false;
|
|
|
|
TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName());
|
|
|
|
return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage,
|
|
|
|
Changed);
|
|
|
|
}
|
|
|
|
|
2014-11-12 10:00:47 +08:00
|
|
|
void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
|
|
|
|
const MultiLevelTemplateArgumentList &Args) {
|
|
|
|
FunctionProtoType::ExceptionSpecInfo ESI =
|
|
|
|
Proto->getExtProtoInfo().ExceptionSpec;
|
|
|
|
|
|
|
|
SmallVector<QualType, 4> ExceptionStorage;
|
2018-08-10 05:09:38 +08:00
|
|
|
if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getEndLoc(),
|
2017-06-08 05:46:22 +08:00
|
|
|
ESI, ExceptionStorage, Args))
|
2014-11-12 10:00:47 +08:00
|
|
|
// On error, recover by dropping the exception specification.
|
|
|
|
ESI.Type = EST_None;
|
|
|
|
|
|
|
|
UpdateExceptionSpec(New, ESI);
|
|
|
|
}
|
|
|
|
|
2020-02-03 21:44:33 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct GetContainedInventedTypeParmVisitor :
|
|
|
|
public TypeVisitor<GetContainedInventedTypeParmVisitor,
|
|
|
|
TemplateTypeParmDecl *> {
|
|
|
|
using TypeVisitor<GetContainedInventedTypeParmVisitor,
|
|
|
|
TemplateTypeParmDecl *>::Visit;
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *Visit(QualType T) {
|
|
|
|
if (T.isNull())
|
|
|
|
return nullptr;
|
|
|
|
return Visit(T.getTypePtr());
|
|
|
|
}
|
|
|
|
// The deduced type itself.
|
|
|
|
TemplateTypeParmDecl *VisitTemplateTypeParmType(
|
|
|
|
const TemplateTypeParmType *T) {
|
|
|
|
if (!T->getDecl()->isImplicit())
|
|
|
|
return nullptr;
|
|
|
|
return T->getDecl();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only these types can contain 'auto' types, and subsequently be replaced
|
|
|
|
// by references to invented parameters.
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitElaboratedType(const ElaboratedType *T) {
|
|
|
|
return Visit(T->getNamedType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitPointerType(const PointerType *T) {
|
|
|
|
return Visit(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitBlockPointerType(const BlockPointerType *T) {
|
|
|
|
return Visit(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitReferenceType(const ReferenceType *T) {
|
|
|
|
return Visit(T->getPointeeTypeAsWritten());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitMemberPointerType(const MemberPointerType *T) {
|
|
|
|
return Visit(T->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitArrayType(const ArrayType *T) {
|
|
|
|
return Visit(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitDependentSizedExtVectorType(
|
|
|
|
const DependentSizedExtVectorType *T) {
|
|
|
|
return Visit(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitVectorType(const VectorType *T) {
|
|
|
|
return Visit(T->getElementType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitFunctionProtoType(const FunctionProtoType *T) {
|
|
|
|
return VisitFunctionType(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitFunctionType(const FunctionType *T) {
|
|
|
|
return Visit(T->getReturnType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitParenType(const ParenType *T) {
|
|
|
|
return Visit(T->getInnerType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitAttributedType(const AttributedType *T) {
|
|
|
|
return Visit(T->getModifiedType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitMacroQualifiedType(const MacroQualifiedType *T) {
|
|
|
|
return Visit(T->getUnderlyingType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitAdjustedType(const AdjustedType *T) {
|
|
|
|
return Visit(T->getOriginalType());
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *VisitPackExpansionType(const PackExpansionType *T) {
|
|
|
|
return Visit(T->getPattern());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
|
2011-01-15 06:40:04 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
2011-05-02 06:35:37 +08:00
|
|
|
int indexAdjustment,
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<unsigned> NumExpansions,
|
2012-01-26 00:15:54 +08:00
|
|
|
bool ExpectParameterPack) {
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo();
|
2014-05-26 14:22:03 +08:00
|
|
|
TypeSourceInfo *NewDI = nullptr;
|
|
|
|
|
2011-01-06 07:12:31 +08:00
|
|
|
TypeLoc OldTL = OldDI->getTypeLoc();
|
2013-02-19 06:06:02 +08:00
|
|
|
if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) {
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
// We have a function parameter pack. Substitute into the pattern of the
|
2011-01-06 07:12:31 +08:00
|
|
|
// expansion.
|
2018-07-31 03:24:48 +08:00
|
|
|
NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs,
|
2011-01-06 07:12:31 +08:00
|
|
|
OldParm->getLocation(), OldParm->getDeclName());
|
|
|
|
if (!NewDI)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2011-01-06 07:12:31 +08:00
|
|
|
if (NewDI->getType()->containsUnexpandedParameterPack()) {
|
|
|
|
// We still have unexpanded parameter packs, which means that
|
|
|
|
// our function parameter is still a function parameter pack.
|
|
|
|
// Therefore, make its type a pack expansion type.
|
2011-01-15 01:04:44 +08:00
|
|
|
NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(),
|
2011-01-15 06:40:04 +08:00
|
|
|
NumExpansions);
|
2012-01-26 00:15:54 +08:00
|
|
|
} else if (ExpectParameterPack) {
|
|
|
|
// We expected to get a parameter pack but didn't (because the type
|
|
|
|
// itself is not a pack expansion type), so complain. This can occur when
|
|
|
|
// the substitution goes through an alias template that "loses" the
|
|
|
|
// pack expansion.
|
2018-07-31 03:24:48 +08:00
|
|
|
Diag(OldParm->getLocation(),
|
2012-01-26 00:15:54 +08:00
|
|
|
diag::err_function_parameter_pack_without_parameter_packs)
|
|
|
|
<< NewDI->getType();
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2018-07-31 03:24:48 +08:00
|
|
|
}
|
2011-01-06 07:12:31 +08:00
|
|
|
} else {
|
2018-07-31 03:24:48 +08:00
|
|
|
NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(),
|
2011-01-06 07:12:31 +08:00
|
|
|
OldParm->getDeclName());
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
if (!NewDI)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
|
|
|
|
if (NewDI->getType()->isVoidType()) {
|
|
|
|
Diag(OldParm->getLocation(), diag::err_param_with_void_type);
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
}
|
|
|
|
|
2020-02-03 21:44:33 +08:00
|
|
|
// In abbreviated templates, TemplateTypeParmDecls with possible
|
|
|
|
// TypeConstraints are created when the parameter list is originally parsed.
|
|
|
|
// The TypeConstraints can therefore reference other functions parameters in
|
|
|
|
// the abbreviated function template, which is why we must instantiate them
|
|
|
|
// here, when the instantiated versions of those referenced parameters are in
|
|
|
|
// scope.
|
|
|
|
if (TemplateTypeParmDecl *TTP =
|
|
|
|
GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) {
|
|
|
|
if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
|
2020-02-07 05:19:18 +08:00
|
|
|
auto *Inst = cast_or_null<TemplateTypeParmDecl>(
|
2020-02-03 21:44:33 +08:00
|
|
|
FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs));
|
|
|
|
// We will first get here when instantiating the abbreviated function
|
|
|
|
// template's described function, but we might also get here later.
|
|
|
|
// Make sure we do not instantiate the TypeConstraint more than once.
|
2020-02-07 05:19:18 +08:00
|
|
|
if (Inst && !Inst->getTypeConstraint()) {
|
2020-02-03 21:44:33 +08:00
|
|
|
// TODO: Concepts: do not instantiate the constraint (delayed constraint
|
|
|
|
// substitution)
|
|
|
|
const ASTTemplateArgumentListInfo *TemplArgInfo
|
|
|
|
= TC->getTemplateArgsAsWritten();
|
|
|
|
TemplateArgumentListInfo InstArgs;
|
|
|
|
|
|
|
|
if (TemplArgInfo) {
|
|
|
|
InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc);
|
|
|
|
InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc);
|
|
|
|
if (Subst(TemplArgInfo->getTemplateArgs(),
|
|
|
|
TemplArgInfo->NumTemplateArgs, InstArgs, TemplateArgs))
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (AttachTypeConstraint(
|
|
|
|
TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(),
|
|
|
|
TC->getNamedConcept(), &InstArgs, Inst,
|
|
|
|
TTP->isParameterPack()
|
|
|
|
? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint())
|
|
|
|
->getEllipsisLoc()
|
|
|
|
: SourceLocation()))
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(),
|
2011-03-08 16:55:46 +08:00
|
|
|
OldParm->getInnerLocStart(),
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
OldParm->getLocation(),
|
2011-03-08 16:55:46 +08:00
|
|
|
OldParm->getIdentifier(),
|
|
|
|
NewDI->getType(), NewDI,
|
2013-04-04 03:27:57 +08:00
|
|
|
OldParm->getStorageClass());
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
if (!NewParm)
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
|
|
|
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
// Mark the (new) default argument as uninstantiated (if any).
|
|
|
|
if (OldParm->hasUninstantiatedDefaultArg()) {
|
|
|
|
Expr *Arg = OldParm->getUninstantiatedDefaultArg();
|
|
|
|
NewParm->setUninstantiatedDefaultArg(Arg);
|
2010-10-13 02:23:32 +08:00
|
|
|
} else if (OldParm->hasUnparsedDefaultArg()) {
|
|
|
|
NewParm->setUnparsedDefaultArg();
|
|
|
|
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
|
2015-06-30 01:50:19 +08:00
|
|
|
} else if (Expr *Arg = OldParm->getDefaultArg()) {
|
|
|
|
FunctionDecl *OwningFunc = cast<FunctionDecl>(OldParm->getDeclContext());
|
2015-08-23 18:22:28 +08:00
|
|
|
if (OwningFunc->isLexicallyWithinFunctionOrMethod()) {
|
|
|
|
// Instantiate default arguments for methods of local classes (DR1484)
|
|
|
|
// and non-defining declarations.
|
|
|
|
Sema::ContextRAII SavedContext(*this, OwningFunc);
|
2016-12-16 11:19:41 +08:00
|
|
|
LocalInstantiationScope Local(*this, true);
|
2015-06-30 01:50:19 +08:00
|
|
|
ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
|
2015-12-11 09:56:36 +08:00
|
|
|
if (NewArg.isUsable()) {
|
|
|
|
// It would be nice if we still had this.
|
2018-08-10 05:08:08 +08:00
|
|
|
SourceLocation EqualLoc = NewArg.get()->getBeginLoc();
|
2015-12-11 09:56:36 +08:00
|
|
|
SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
|
|
|
|
}
|
2015-06-30 01:50:19 +08:00
|
|
|
} else {
|
|
|
|
// FIXME: if we non-lazily instantiated non-dependent default args for
|
|
|
|
// non-dependent parameter types we could remove a bunch of duplicate
|
|
|
|
// conversion warnings for such arguments.
|
|
|
|
NewParm->setUninstantiatedDefaultArg(Arg);
|
|
|
|
}
|
|
|
|
}
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
|
|
|
|
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
|
2018-07-31 03:24:48 +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-08 00:43:16 +08:00
|
|
|
if (OldParm->isParameterPack() && !NewParm->isParameterPack()) {
|
2012-01-25 10:14:59 +08:00
|
|
|
// Add the new parameter to the instantiated parameter pack.
|
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-08 00:43:16 +08:00
|
|
|
CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm);
|
|
|
|
} else {
|
|
|
|
// Introduce an Old -> New mapping
|
2018-07-31 03:24:48 +08:00
|
|
|
CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
|
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-08 00:43:16 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-07-19 18:14:41 +08:00
|
|
|
// FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
|
|
|
|
// can be anything, is this right ?
|
2010-07-14 05:05:02 +08:00
|
|
|
NewParm->setDeclContext(CurContext);
|
2011-05-02 06:35:37 +08:00
|
|
|
|
|
|
|
NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(),
|
|
|
|
OldParm->getFunctionScopeIndex() + indexAdjustment);
|
2013-03-09 06:25:36 +08:00
|
|
|
|
|
|
|
InstantiateAttrs(TemplateArgs, OldParm, NewParm);
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
return NewParm;
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Substitute the given template arguments into the given set of
|
2011-01-07 08:20:55 +08:00
|
|
|
/// parameters, producing the set of parameter types that would be generated
|
|
|
|
/// from such a substitution.
|
2016-06-24 12:05:48 +08:00
|
|
|
bool Sema::SubstParmTypes(
|
|
|
|
SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
|
|
|
|
const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
|
|
|
SmallVectorImpl<QualType> &ParamTypes,
|
|
|
|
SmallVectorImpl<ParmVarDecl *> *OutParams,
|
|
|
|
ExtParameterInfoBuilder &ParamInfos) {
|
2017-02-23 09:43:54 +08:00
|
|
|
assert(!CodeSynthesisContexts.empty() &&
|
2011-01-07 08:20:55 +08:00
|
|
|
"Cannot perform an instantiation without some context on the "
|
|
|
|
"instantiation stack");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
|
2011-01-07 08:20:55 +08:00
|
|
|
DeclarationName());
|
2016-06-24 12:05:48 +08:00
|
|
|
return Instantiator.TransformFunctionTypeParams(
|
|
|
|
Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos);
|
2011-01-07 08:20:55 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Perform substitution on the base class specifiers of the
|
2009-08-26 06:02:44 +08:00
|
|
|
/// given class template specialization.
|
2009-03-03 12:44:36 +08:00
|
|
|
///
|
|
|
|
/// Produces a diagnostic and returns true on error, returns false and
|
|
|
|
/// attaches the instantiated base classes to the class template
|
|
|
|
/// specialization if successful.
|
2009-09-09 23:08:12 +08:00
|
|
|
bool
|
2009-08-26 06:02:44 +08:00
|
|
|
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|
|
|
CXXRecordDecl *Pattern,
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-03-03 12:44:36 +08:00
|
|
|
bool Invalid = false;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
|
2015-04-15 09:21:42 +08:00
|
|
|
for (const auto &Base : Pattern->bases()) {
|
2014-03-13 23:41:46 +08:00
|
|
|
if (!Base.getType()->isDependentType()) {
|
|
|
|
if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl()) {
|
2013-06-22 02:58:32 +08:00
|
|
|
if (RD->isInvalidDecl())
|
|
|
|
Instantiation->setInvalidDecl();
|
|
|
|
}
|
2014-03-13 23:41:46 +08:00
|
|
|
InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(Base));
|
2009-03-03 12:44:36 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-01-04 06:36:02 +08:00
|
|
|
SourceLocation EllipsisLoc;
|
2011-03-02 10:04:06 +08:00
|
|
|
TypeSourceInfo *BaseTypeLoc;
|
2014-03-13 23:41:46 +08:00
|
|
|
if (Base.isPackExpansion()) {
|
2011-01-04 06:36:02 +08:00
|
|
|
// This is a pack expansion. See whether we should expand it now, or
|
|
|
|
// wait until later.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2014-03-13 23:41:46 +08:00
|
|
|
collectUnexpandedParameterPacks(Base.getTypeSourceInfo()->getTypeLoc(),
|
2011-01-04 06:36:02 +08:00
|
|
|
Unexpanded);
|
|
|
|
bool ShouldExpand = false;
|
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 15:32:04 +08:00
|
|
|
bool RetainExpansion = false;
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<unsigned> NumExpansions;
|
2018-07-31 03:24:48 +08:00
|
|
|
if (CheckParameterPacksForExpansion(Base.getEllipsisLoc(),
|
2014-03-13 23:41:46 +08:00
|
|
|
Base.getSourceRange(),
|
2011-09-22 10:34:54 +08:00
|
|
|
Unexpanded,
|
2018-07-31 03:24:48 +08:00
|
|
|
TemplateArgs, ShouldExpand,
|
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 15:32:04 +08:00
|
|
|
RetainExpansion,
|
2011-01-04 06:36:02 +08:00
|
|
|
NumExpansions)) {
|
|
|
|
Invalid = true;
|
2011-01-04 08:32:56 +08:00
|
|
|
continue;
|
2011-01-04 06:36:02 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-04 06:36:02 +08:00
|
|
|
// If we should expand this pack expansion now, do so.
|
|
|
|
if (ShouldExpand) {
|
2011-01-15 01:04:44 +08:00
|
|
|
for (unsigned I = 0; I != *NumExpansions; ++I) {
|
2011-01-04 06:36:02 +08:00
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2014-03-13 23:41:46 +08:00
|
|
|
TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
|
2011-01-04 06:36:02 +08:00
|
|
|
TemplateArgs,
|
2014-03-13 23:41:46 +08:00
|
|
|
Base.getSourceRange().getBegin(),
|
2011-01-04 06:36:02 +08:00
|
|
|
DeclarationName());
|
|
|
|
if (!BaseTypeLoc) {
|
|
|
|
Invalid = true;
|
|
|
|
continue;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-04 06:36:02 +08:00
|
|
|
if (CXXBaseSpecifier *InstantiatedBase
|
|
|
|
= CheckBaseSpecifier(Instantiation,
|
2014-03-13 23:41:46 +08:00
|
|
|
Base.getSourceRange(),
|
|
|
|
Base.isVirtual(),
|
|
|
|
Base.getAccessSpecifierAsWritten(),
|
2011-01-04 06:36:02 +08:00
|
|
|
BaseTypeLoc,
|
|
|
|
SourceLocation()))
|
|
|
|
InstantiatedBases.push_back(InstantiatedBase);
|
|
|
|
else
|
|
|
|
Invalid = true;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-04 06:36:02 +08:00
|
|
|
continue;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-04 06:36:02 +08:00
|
|
|
// The resulting base specifier will (still) be a pack expansion.
|
2014-03-13 23:41:46 +08:00
|
|
|
EllipsisLoc = Base.getEllipsisLoc();
|
2011-03-02 10:04:06 +08:00
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
|
2014-03-13 23:41:46 +08:00
|
|
|
BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
|
2011-03-02 10:04:06 +08:00
|
|
|
TemplateArgs,
|
2014-03-13 23:41:46 +08:00
|
|
|
Base.getSourceRange().getBegin(),
|
2011-03-02 10:04:06 +08:00
|
|
|
DeclarationName());
|
|
|
|
} else {
|
2014-03-13 23:41:46 +08:00
|
|
|
BaseTypeLoc = SubstType(Base.getTypeSourceInfo(),
|
2011-03-02 10:04:06 +08:00
|
|
|
TemplateArgs,
|
2014-03-13 23:41:46 +08:00
|
|
|
Base.getSourceRange().getBegin(),
|
2011-03-02 10:04:06 +08:00
|
|
|
DeclarationName());
|
2011-01-04 06:36:02 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-07-27 00:56:01 +08:00
|
|
|
if (!BaseTypeLoc) {
|
2009-03-03 12:44:36 +08:00
|
|
|
Invalid = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CXXBaseSpecifier *InstantiatedBase
|
2009-03-26 05:17:03 +08:00
|
|
|
= CheckBaseSpecifier(Instantiation,
|
2014-03-13 23:41:46 +08:00
|
|
|
Base.getSourceRange(),
|
|
|
|
Base.isVirtual(),
|
|
|
|
Base.getAccessSpecifierAsWritten(),
|
2011-01-04 06:36:02 +08:00
|
|
|
BaseTypeLoc,
|
|
|
|
EllipsisLoc))
|
2009-03-03 12:44:36 +08:00
|
|
|
InstantiatedBases.push_back(InstantiatedBase);
|
|
|
|
else
|
|
|
|
Invalid = true;
|
|
|
|
}
|
|
|
|
|
2015-12-28 05:55:19 +08:00
|
|
|
if (!Invalid && AttachBaseSpecifiers(Instantiation, InstantiatedBases))
|
2009-03-03 12:44:36 +08:00
|
|
|
Invalid = true;
|
|
|
|
|
|
|
|
return Invalid;
|
|
|
|
}
|
|
|
|
|
2012-01-21 06:50:54 +08:00
|
|
|
// Defined via #include from SemaTemplateInstantiateDecl.cpp
|
2012-02-06 19:13:08 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace sema {
|
|
|
|
Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
2017-03-24 02:51:54 +08:00
|
|
|
Attr *instantiateTemplateAttributeForDecl(
|
|
|
|
const Attr *At, ASTContext &C, Sema &S,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
2012-02-06 19:13:08 +08:00
|
|
|
}
|
|
|
|
}
|
2012-01-21 06:50:54 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Instantiate the definition of a class from a given pattern.
|
2009-03-26 05:17:03 +08:00
|
|
|
///
|
|
|
|
/// \param PointOfInstantiation The point of instantiation within the
|
|
|
|
/// source code.
|
|
|
|
///
|
|
|
|
/// \param Instantiation is the declaration whose definition is being
|
|
|
|
/// instantiated. This will be either a class template specialization
|
|
|
|
/// or a member class of a class template specialization.
|
|
|
|
///
|
|
|
|
/// \param Pattern is the pattern from which the instantiation
|
|
|
|
/// occurs. This will be either the declaration of a class template or
|
|
|
|
/// the declaration of a member class of a class template.
|
|
|
|
///
|
|
|
|
/// \param TemplateArgs The template arguments to be substituted into
|
|
|
|
/// the pattern.
|
|
|
|
///
|
2009-09-05 06:48:11 +08:00
|
|
|
/// \param TSK the kind of implicit or explicit instantiation to perform.
|
2009-08-24 23:23:48 +08:00
|
|
|
///
|
|
|
|
/// \param Complain whether to complain if the class cannot be instantiated due
|
|
|
|
/// to the lack of a definition.
|
|
|
|
///
|
2009-03-26 05:17:03 +08:00
|
|
|
/// \returns true if an error occurred, false otherwise.
|
|
|
|
bool
|
|
|
|
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|
|
|
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
2009-09-05 06:48:11 +08:00
|
|
|
TemplateSpecializationKind TSK,
|
2009-08-24 23:23:48 +08:00
|
|
|
bool Complain) {
|
2009-09-09 23:08:12 +08:00
|
|
|
CXXRecordDecl *PatternDef
|
2010-02-11 09:04:33 +08:00
|
|
|
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
|
2016-08-19 06:01:25 +08:00
|
|
|
if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
|
2012-03-15 07:13:10 +08:00
|
|
|
Instantiation->getInstantiatedFromMemberClass(),
|
|
|
|
Pattern, PatternDef, TSK, Complain))
|
2009-03-03 12:44:36 +08:00
|
|
|
return true;
|
2019-03-30 16:42:48 +08:00
|
|
|
|
|
|
|
llvm::TimeTraceScope TimeScope("InstantiateClass", [&]() {
|
2019-05-12 18:39:21 +08:00
|
|
|
std::string Name;
|
|
|
|
llvm::raw_string_ostream OS(Name);
|
|
|
|
Instantiation->getNameForDiagnostic(OS, getPrintingPolicy(),
|
|
|
|
/*Qualified=*/true);
|
|
|
|
return Name;
|
2019-03-30 16:42:48 +08:00
|
|
|
});
|
|
|
|
|
2009-03-26 05:17:03 +08:00
|
|
|
Pattern = PatternDef;
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
// Record the point of instantiation.
|
2018-07-31 03:24:48 +08:00
|
|
|
if (MemberSpecializationInfo *MSInfo
|
2009-10-15 23:54:05 +08:00
|
|
|
= Instantiation->getMemberSpecializationInfo()) {
|
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
|
|
|
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
2018-07-31 03:24:48 +08:00
|
|
|
} else if (ClassTemplateSpecializationDecl *Spec
|
2011-12-21 04:32:49 +08:00
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
|
2009-10-27 14:26:26 +08:00
|
|
|
Spec->setTemplateSpecializationKind(TSK);
|
|
|
|
Spec->setPointOfInstantiation(PointOfInstantiation);
|
2009-10-15 23:54:05 +08:00
|
|
|
}
|
2014-03-10 08:04:29 +08:00
|
|
|
|
2009-03-26 05:23:52 +08:00
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
|
2013-10-08 16:09:04 +08:00
|
|
|
if (Inst.isInvalid())
|
2009-03-10 08:06:19 +08:00
|
|
|
return true;
|
2016-08-31 10:15:21 +08:00
|
|
|
assert(!Inst.isAlreadyInstantiating() && "should have been caught by caller");
|
2018-03-23 08:07:18 +08:00
|
|
|
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
|
2016-05-27 04:23:13 +08:00
|
|
|
"instantiating class definition");
|
2009-03-10 08:06:19 +08:00
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
2010-04-29 08:35:03 +08:00
|
|
|
ContextRAII SavedContext(*this, Instantiation);
|
2017-04-02 05:30:49 +08:00
|
|
|
EnterExpressionEvaluationContext EvalContext(
|
|
|
|
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2010-03-24 09:33:17 +08:00
|
|
|
// If this is an instantiation of a local class, merge this local
|
|
|
|
// instantiation scope with the enclosing scope. Otherwise, every
|
|
|
|
// instantiation of a class has its own local instantiation scope.
|
|
|
|
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(*this, MergeWithParentScope);
|
2010-03-24 09:33:17 +08:00
|
|
|
|
2017-09-22 03:54:12 +08:00
|
|
|
// Some class state isn't processed immediately but delayed till class
|
|
|
|
// instantiation completes. We may not be ready to handle any delayed state
|
|
|
|
// already on the stack as it might correspond to a different class, so save
|
|
|
|
// it now and put it back later.
|
|
|
|
SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this);
|
2016-02-27 03:51:02 +08:00
|
|
|
|
2010-08-01 10:01:53 +08:00
|
|
|
// Pull attributes from the pattern onto the instantiation.
|
|
|
|
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Start the definition of this instantiation.
|
2009-03-26 05:17:03 +08:00
|
|
|
Instantiation->startDefinition();
|
2014-03-10 08:04:29 +08:00
|
|
|
|
|
|
|
// The instantiation is visible here, even if it was first declared in an
|
|
|
|
// unimported module.
|
2017-06-23 09:04:34 +08:00
|
|
|
Instantiation->setVisibleDespiteOwningModule();
|
2014-03-10 08:04:29 +08:00
|
|
|
|
|
|
|
// FIXME: This loses the as-written tag kind for an explicit instantiation.
|
2010-05-06 08:28:52 +08:00
|
|
|
Instantiation->setTagKind(Pattern->getTagKind());
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2009-08-26 06:02:44 +08:00
|
|
|
// Do substitution on the base class specifiers.
|
|
|
|
if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
|
2012-07-03 05:00:41 +08:00
|
|
|
Instantiation->setInvalidDecl();
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2010-11-11 03:44:59 +08:00
|
|
|
TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Decl*, 4> Fields;
|
2012-01-21 06:50:54 +08:00
|
|
|
// Delay instantiation of late parsed attributes.
|
|
|
|
LateInstantiatedAttrVec LateAttrs;
|
|
|
|
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
|
|
|
|
|
2019-05-14 07:35:21 +08:00
|
|
|
bool MightHaveConstexprVirtualFunctions = false;
|
2014-03-08 03:56:05 +08:00
|
|
|
for (auto *Member : Pattern->decls()) {
|
2010-11-04 11:18:57 +08:00
|
|
|
// Don't instantiate members not belonging in this semantic context.
|
|
|
|
// e.g. for:
|
|
|
|
// @code
|
|
|
|
// template <int i> class A {
|
|
|
|
// class B *g;
|
|
|
|
// };
|
|
|
|
// @endcode
|
|
|
|
// 'class B' has the template as lexical context but semantically it is
|
|
|
|
// introduced in namespace scope.
|
2014-03-08 03:56:05 +08:00
|
|
|
if (Member->getDeclContext() != Pattern)
|
2010-11-04 11:18:57 +08:00
|
|
|
continue;
|
|
|
|
|
2018-07-24 06:47:37 +08:00
|
|
|
// BlockDecls can appear in a default-member-initializer. They must be the
|
|
|
|
// child of a BlockExpr, so we only know how to instantiate them from there.
|
|
|
|
if (isa<BlockDecl>(Member))
|
|
|
|
continue;
|
|
|
|
|
2014-03-08 03:56:05 +08:00
|
|
|
if (Member->isInvalidDecl()) {
|
2012-07-12 06:37:56 +08:00
|
|
|
Instantiation->setInvalidDecl();
|
2010-11-11 03:44:59 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-03-08 03:56:05 +08:00
|
|
|
Decl *NewMember = Instantiator.Visit(Member);
|
2009-03-18 05:15:40 +08:00
|
|
|
if (NewMember) {
|
2011-06-12 01:19:42 +08:00
|
|
|
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) {
|
2010-08-21 17:40:31 +08:00
|
|
|
Fields.push_back(Field);
|
2012-03-23 11:33:32 +08:00
|
|
|
} else if (EnumDecl *Enum = dyn_cast<EnumDecl>(NewMember)) {
|
|
|
|
// C++11 [temp.inst]p1: The implicit instantiation of a class template
|
|
|
|
// specialization causes the implicit instantiation of the definitions
|
|
|
|
// of unscoped member enumerations.
|
|
|
|
// Record a point of instantiation for this implicit instantiation.
|
2012-03-24 07:09:08 +08:00
|
|
|
if (TSK == TSK_ImplicitInstantiation && !Enum->isScoped() &&
|
|
|
|
Enum->isCompleteDefinition()) {
|
2012-03-23 11:33:32 +08:00
|
|
|
MemberSpecializationInfo *MSInfo =Enum->getMemberSpecializationInfo();
|
|
|
|
assert(MSInfo && "no spec info for member enum specialization");
|
|
|
|
MSInfo->setTemplateSpecializationKind(TSK_ImplicitInstantiation);
|
|
|
|
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
|
|
|
}
|
2012-07-12 06:37:56 +08:00
|
|
|
} else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(NewMember)) {
|
|
|
|
if (SA->isFailed()) {
|
|
|
|
// A static_assert failed. Bail out; instantiating this
|
|
|
|
// class is probably not meaningful.
|
|
|
|
Instantiation->setInvalidDecl();
|
|
|
|
break;
|
|
|
|
}
|
2019-05-14 07:35:21 +08:00
|
|
|
} else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
|
|
|
|
if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
|
|
|
|
(MD->isVirtualAsWritten() || Instantiation->getNumBases()))
|
|
|
|
MightHaveConstexprVirtualFunctions = true;
|
2012-03-23 11:33:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NewMember->isInvalidDecl())
|
2012-07-03 05:00:41 +08:00
|
|
|
Instantiation->setInvalidDecl();
|
2009-03-18 05:15:40 +08:00
|
|
|
} else {
|
|
|
|
// FIXME: Eventually, a NULL return will mean that one of the
|
2012-07-03 05:00:41 +08:00
|
|
|
// instantiations was a semantic disaster, and we'll want to mark the
|
|
|
|
// declaration invalid.
|
|
|
|
// For now, we expect to skip some members that we can't yet handle.
|
2009-03-12 00:48:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-12 02:59:21 +08:00
|
|
|
// Finish checking fields.
|
2014-05-26 14:22:03 +08:00
|
|
|
ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
|
2018-07-13 05:09:05 +08:00
|
|
|
SourceLocation(), SourceLocation(), ParsedAttributesView());
|
2019-12-06 05:37:35 +08:00
|
|
|
CheckCompletedCXXClass(nullptr, Instantiation);
|
2011-06-12 01:19:42 +08:00
|
|
|
|
2015-03-18 05:51:43 +08:00
|
|
|
// Default arguments are parsed, if not instantiated. We can go instantiate
|
2019-12-02 23:25:23 +08:00
|
|
|
// default arg exprs for default constructors if necessary now. Unless we're
|
|
|
|
// parsing a class, in which case wait until that's finished.
|
|
|
|
if (ParsingClassDepth == 0)
|
|
|
|
ActOnFinishCXXNonNestedClass();
|
2015-03-18 05:51:43 +08:00
|
|
|
|
2012-01-21 06:50:54 +08:00
|
|
|
// Instantiate late parsed attributes, and attach them to their decls.
|
|
|
|
// See Sema::InstantiateAttrs
|
|
|
|
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
|
|
|
|
E = LateAttrs.end(); I != E; ++I) {
|
|
|
|
assert(CurrentInstantiationScope == Instantiator.getStartingScope());
|
|
|
|
CurrentInstantiationScope = I->Scope;
|
2013-06-07 10:33:37 +08:00
|
|
|
|
|
|
|
// Allow 'this' within late-parsed attributes.
|
|
|
|
NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
|
|
|
|
CXXRecordDecl *ThisContext =
|
|
|
|
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
2018-12-13 18:15:27 +08:00
|
|
|
CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(),
|
2013-06-07 10:33:37 +08:00
|
|
|
ND && ND->isCXXInstanceMember());
|
|
|
|
|
2012-01-21 06:50:54 +08:00
|
|
|
Attr *NewAttr =
|
|
|
|
instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
|
|
|
|
I->NewDecl->addAttr(NewAttr);
|
|
|
|
LocalInstantiationScope::deleteScopes(I->Scope,
|
|
|
|
Instantiator.getStartingScope());
|
|
|
|
}
|
|
|
|
Instantiator.disableLateAttributeInstantiation();
|
|
|
|
LateAttrs.clear();
|
|
|
|
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
ActOnFinishDelayedMemberInitializers(Instantiation);
|
2011-06-12 01:19:42 +08:00
|
|
|
|
2014-03-10 08:04:29 +08:00
|
|
|
// FIXME: We should do something similar for explicit instantiations so they
|
|
|
|
// end up in the right module.
|
2011-11-18 16:08:52 +08:00
|
|
|
if (TSK == TSK_ImplicitInstantiation) {
|
2012-02-11 09:59:57 +08:00
|
|
|
Instantiation->setLocation(Pattern->getLocation());
|
2011-11-18 16:08:52 +08:00
|
|
|
Instantiation->setLocStart(Pattern->getInnerLocStart());
|
2016-07-16 02:11:33 +08:00
|
|
|
Instantiation->setBraceRange(Pattern->getBraceRange());
|
2011-11-18 16:08:52 +08:00
|
|
|
}
|
2011-10-04 04:34:03 +08:00
|
|
|
|
2012-07-03 05:00:41 +08:00
|
|
|
if (!Instantiation->isInvalidDecl()) {
|
2012-08-10 11:15:35 +08:00
|
|
|
// Perform any dependent diagnostics from the pattern.
|
|
|
|
PerformDependentDiagnostics(Pattern, TemplateArgs);
|
|
|
|
|
2010-11-11 03:44:59 +08:00
|
|
|
// Instantiate any out-of-line class template partial
|
|
|
|
// specializations now.
|
2013-09-26 11:49:48 +08:00
|
|
|
for (TemplateDeclInstantiator::delayed_partial_spec_iterator
|
2010-11-11 03:44:59 +08:00
|
|
|
P = Instantiator.delayed_partial_spec_begin(),
|
|
|
|
PEnd = Instantiator.delayed_partial_spec_end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
|
2013-09-26 11:49:48 +08:00
|
|
|
P->first, P->second)) {
|
|
|
|
Instantiation->setInvalidDecl();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate any out-of-line variable template partial
|
|
|
|
// specializations now.
|
|
|
|
for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator
|
|
|
|
P = Instantiator.delayed_var_partial_spec_begin(),
|
|
|
|
PEnd = Instantiator.delayed_var_partial_spec_end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (!Instantiator.InstantiateVarTemplatePartialSpecialization(
|
|
|
|
P->first, P->second)) {
|
2012-07-03 05:00:41 +08:00
|
|
|
Instantiation->setInvalidDecl();
|
2010-11-11 03:44:59 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-03 12:44:36 +08:00
|
|
|
// Exit the scope of this instantiation.
|
2010-04-29 08:35:03 +08:00
|
|
|
SavedContext.pop();
|
2009-03-03 12:44:36 +08:00
|
|
|
|
2012-07-03 05:00:41 +08:00
|
|
|
if (!Instantiation->isInvalidDecl()) {
|
2009-05-27 04:50:29 +08:00
|
|
|
Consumer.HandleTagDeclDefinition(Instantiation);
|
|
|
|
|
Rework when and how vtables are emitted, by tracking where vtables are
"used" (e.g., we will refer to the vtable in the generated code) and
when they are defined (i.e., because we've seen the key function
definition). Previously, we were effectively tracking "potential
definitions" rather than uses, so we were a bit too eager about emitting
vtables for classes without key functions.
The new scheme:
- For every use of a vtable, Sema calls MarkVTableUsed() to indicate
the use. For example, this occurs when calling a virtual member
function of the class, defining a constructor of that class type,
dynamic_cast'ing from that type to a derived class, casting
to/through a virtual base class, etc.
- For every definition of a vtable, Sema calls MarkVTableUsed() to
indicate the definition. This happens at the end of the translation
unit for classes whose key function has been defined (so we can
delay computation of the key function; see PR6564), and will also
occur with explicit template instantiation definitions.
- For every vtable defined/used, we mark all of the virtual member
functions of that vtable as defined/used, unless we know that the key
function is in another translation unit. This instantiates virtual
member functions when needed.
- At the end of the translation unit, Sema tells CodeGen (via the
ASTConsumer) which vtables must be defined (CodeGen will define
them) and which may be used (for which CodeGen will define the
vtables lazily).
From a language perspective, both the old and the new schemes are
permissible: we're allowed to instantiate virtual member functions
whenever we want per the standard. However, all other C++ compilers
were more lazy than we were, and our eagerness was both a performance
issue (we instantiated too much) and a portability problem (we broke
Boost test cases, which now pass).
Notes:
(1) There's a ton of churn in the tests, because the order in which
vtables get emitted to IR has changed. I've tried to isolate some of
the larger tests from these issues.
(2) Some diagnostics related to
implicitly-instantiated/implicitly-defined virtual member functions
have moved to the point of first use/definition. It's better this
way.
(3) I could use a review of the places where we MarkVTableUsed, to
see if I missed any place where the language effectively requires a
vtable.
Fixes PR7114 and PR6564.
llvm-svn: 103718
2010-05-14 00:44:06 +08:00
|
|
|
// Always emit the vtable for an explicit instantiation definition
|
2019-05-14 07:35:21 +08:00
|
|
|
// of a polymorphic class template specialization. Otherwise, eagerly
|
|
|
|
// instantiate only constexpr virtual functions in preparation for their use
|
|
|
|
// in constant evaluation.
|
Rework when and how vtables are emitted, by tracking where vtables are
"used" (e.g., we will refer to the vtable in the generated code) and
when they are defined (i.e., because we've seen the key function
definition). Previously, we were effectively tracking "potential
definitions" rather than uses, so we were a bit too eager about emitting
vtables for classes without key functions.
The new scheme:
- For every use of a vtable, Sema calls MarkVTableUsed() to indicate
the use. For example, this occurs when calling a virtual member
function of the class, defining a constructor of that class type,
dynamic_cast'ing from that type to a derived class, casting
to/through a virtual base class, etc.
- For every definition of a vtable, Sema calls MarkVTableUsed() to
indicate the definition. This happens at the end of the translation
unit for classes whose key function has been defined (so we can
delay computation of the key function; see PR6564), and will also
occur with explicit template instantiation definitions.
- For every vtable defined/used, we mark all of the virtual member
functions of that vtable as defined/used, unless we know that the key
function is in another translation unit. This instantiates virtual
member functions when needed.
- At the end of the translation unit, Sema tells CodeGen (via the
ASTConsumer) which vtables must be defined (CodeGen will define
them) and which may be used (for which CodeGen will define the
vtables lazily).
From a language perspective, both the old and the new schemes are
permissible: we're allowed to instantiate virtual member functions
whenever we want per the standard. However, all other C++ compilers
were more lazy than we were, and our eagerness was both a performance
issue (we instantiated too much) and a portability problem (we broke
Boost test cases, which now pass).
Notes:
(1) There's a ton of churn in the tests, because the order in which
vtables get emitted to IR has changed. I've tried to isolate some of
the larger tests from these issues.
(2) Some diagnostics related to
implicitly-instantiated/implicitly-defined virtual member functions
have moved to the point of first use/definition. It's better this
way.
(3) I could use a review of the places where we MarkVTableUsed, to
see if I missed any place where the language effectively requires a
vtable.
Fixes PR7114 and PR6564.
llvm-svn: 103718
2010-05-14 00:44:06 +08:00
|
|
|
if (TSK == TSK_ExplicitInstantiationDefinition)
|
|
|
|
MarkVTableUsed(PointOfInstantiation, Instantiation, true);
|
2019-05-14 07:35:21 +08:00
|
|
|
else if (MightHaveConstexprVirtualFunctions)
|
|
|
|
MarkVirtualMembersReferenced(PointOfInstantiation, Instantiation,
|
|
|
|
/*ConstexprOnly*/ true);
|
Rework when and how vtables are emitted, by tracking where vtables are
"used" (e.g., we will refer to the vtable in the generated code) and
when they are defined (i.e., because we've seen the key function
definition). Previously, we were effectively tracking "potential
definitions" rather than uses, so we were a bit too eager about emitting
vtables for classes without key functions.
The new scheme:
- For every use of a vtable, Sema calls MarkVTableUsed() to indicate
the use. For example, this occurs when calling a virtual member
function of the class, defining a constructor of that class type,
dynamic_cast'ing from that type to a derived class, casting
to/through a virtual base class, etc.
- For every definition of a vtable, Sema calls MarkVTableUsed() to
indicate the definition. This happens at the end of the translation
unit for classes whose key function has been defined (so we can
delay computation of the key function; see PR6564), and will also
occur with explicit template instantiation definitions.
- For every vtable defined/used, we mark all of the virtual member
functions of that vtable as defined/used, unless we know that the key
function is in another translation unit. This instantiates virtual
member functions when needed.
- At the end of the translation unit, Sema tells CodeGen (via the
ASTConsumer) which vtables must be defined (CodeGen will define
them) and which may be used (for which CodeGen will define the
vtables lazily).
From a language perspective, both the old and the new schemes are
permissible: we're allowed to instantiate virtual member functions
whenever we want per the standard. However, all other C++ compilers
were more lazy than we were, and our eagerness was both a performance
issue (we instantiated too much) and a portability problem (we broke
Boost test cases, which now pass).
Notes:
(1) There's a ton of churn in the tests, because the order in which
vtables get emitted to IR has changed. I've tried to isolate some of
the larger tests from these issues.
(2) Some diagnostics related to
implicitly-instantiated/implicitly-defined virtual member functions
have moved to the point of first use/definition. It's better this
way.
(3) I could use a review of the places where we MarkVTableUsed, to
see if I missed any place where the language effectively requires a
vtable.
Fixes PR7114 and PR6564.
llvm-svn: 103718
2010-05-14 00:44:06 +08:00
|
|
|
}
|
|
|
|
|
2012-07-03 05:00:41 +08:00
|
|
|
return Instantiation->isInvalidDecl();
|
2009-03-03 12:44:36 +08:00
|
|
|
}
|
Introduce a new expression type, UnresolvedDeclRefExpr, that describes
dependent qualified-ids such as
Fibonacci<N - 1>::value
where N is a template parameter. These references are "unresolved"
because the name is dependent and, therefore, cannot be resolved to a
declaration node (as we would do for a DeclRefExpr or
QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
DeclRefExprs, QualifiedDeclRefExprs, etc.
Also, be a bit more careful about keeping only a single set of
specializations for a class template, and instantiating from the
definition of that template rather than a previous declaration. In
general, we need a better solution for this for all TagDecls, because
it's too easy to accidentally look at a declaration that isn't the
definition.
We can now process a simple Fibonacci computation described as a
template metaprogram.
llvm-svn: 67308
2009-03-20 01:26:29 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Instantiate the definition of an enum from a given pattern.
|
2012-03-15 07:13:10 +08:00
|
|
|
///
|
|
|
|
/// \param PointOfInstantiation The point of instantiation within the
|
|
|
|
/// source code.
|
|
|
|
/// \param Instantiation is the declaration whose definition is being
|
|
|
|
/// instantiated. This will be a member enumeration of a class
|
|
|
|
/// temploid specialization, or a local enumeration within a
|
|
|
|
/// function temploid specialization.
|
|
|
|
/// \param Pattern The templated declaration from which the instantiation
|
|
|
|
/// occurs.
|
|
|
|
/// \param TemplateArgs The template arguments to be substituted into
|
|
|
|
/// the pattern.
|
|
|
|
/// \param TSK The kind of implicit or explicit instantiation to perform.
|
|
|
|
///
|
|
|
|
/// \return \c true if an error occurred, \c false otherwise.
|
|
|
|
bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation,
|
|
|
|
EnumDecl *Instantiation, EnumDecl *Pattern,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
|
|
|
TemplateSpecializationKind TSK) {
|
|
|
|
EnumDecl *PatternDef = Pattern->getDefinition();
|
2016-08-19 06:01:25 +08:00
|
|
|
if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
|
2012-03-15 07:13:10 +08:00
|
|
|
Instantiation->getInstantiatedFromMemberEnum(),
|
|
|
|
Pattern, PatternDef, TSK,/*Complain*/true))
|
|
|
|
return true;
|
|
|
|
Pattern = PatternDef;
|
|
|
|
|
|
|
|
// Record the point of instantiation.
|
|
|
|
if (MemberSpecializationInfo *MSInfo
|
|
|
|
= Instantiation->getMemberSpecializationInfo()) {
|
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
|
|
|
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
|
|
|
}
|
|
|
|
|
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
|
2013-10-08 16:09:04 +08:00
|
|
|
if (Inst.isInvalid())
|
2012-03-15 07:13:10 +08:00
|
|
|
return true;
|
2016-08-31 10:15:21 +08:00
|
|
|
if (Inst.isAlreadyInstantiating())
|
|
|
|
return false;
|
2018-03-23 08:07:18 +08:00
|
|
|
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
|
2016-05-27 04:23:13 +08:00
|
|
|
"instantiating enum definition");
|
2012-03-15 07:13:10 +08:00
|
|
|
|
2014-03-10 08:04:29 +08:00
|
|
|
// The instantiation is visible here, even if it was first declared in an
|
|
|
|
// unimported module.
|
2017-06-23 09:04:34 +08:00
|
|
|
Instantiation->setVisibleDespiteOwningModule();
|
2014-03-10 08:04:29 +08:00
|
|
|
|
2012-03-15 07:13:10 +08:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
|
|
|
ContextRAII SavedContext(*this, Instantiation);
|
2017-04-02 05:30:49 +08:00
|
|
|
EnterExpressionEvaluationContext EvalContext(
|
|
|
|
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
2012-03-15 07:13:10 +08:00
|
|
|
|
|
|
|
LocalInstantiationScope Scope(*this, /*MergeWithParentScope*/true);
|
|
|
|
|
|
|
|
// Pull attributes from the pattern onto the instantiation.
|
|
|
|
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
|
|
|
|
|
|
|
|
TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs);
|
|
|
|
Instantiator.InstantiateEnumDefinition(Instantiation, Pattern);
|
|
|
|
|
|
|
|
// Exit the scope of this instantiation.
|
|
|
|
SavedContext.pop();
|
|
|
|
|
|
|
|
return Instantiation->isInvalidDecl();
|
|
|
|
}
|
|
|
|
|
2014-11-18 07:36:45 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Instantiate the definition of a field from the given pattern.
|
2014-11-18 07:36:45 +08:00
|
|
|
///
|
|
|
|
/// \param PointOfInstantiation The point of instantiation within the
|
|
|
|
/// source code.
|
|
|
|
/// \param Instantiation is the declaration whose definition is being
|
|
|
|
/// instantiated. This will be a class of a class temploid
|
|
|
|
/// specialization, or a local enumeration within a function temploid
|
|
|
|
/// specialization.
|
|
|
|
/// \param Pattern The templated declaration from which the instantiation
|
|
|
|
/// occurs.
|
|
|
|
/// \param TemplateArgs The template arguments to be substituted into
|
|
|
|
/// the pattern.
|
|
|
|
///
|
|
|
|
/// \return \c true if an error occurred, \c false otherwise.
|
|
|
|
bool Sema::InstantiateInClassInitializer(
|
|
|
|
SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
|
|
|
|
FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) {
|
|
|
|
// If there is no initializer, we don't need to do anything.
|
|
|
|
if (!Pattern->hasInClassInitializer())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
assert(Instantiation->getInClassInitStyle() ==
|
|
|
|
Pattern->getInClassInitStyle() &&
|
|
|
|
"pattern and instantiation disagree about init style");
|
|
|
|
|
|
|
|
// Error out if we haven't parsed the initializer of the pattern yet because
|
|
|
|
// we are waiting for the closing brace of the outer class.
|
|
|
|
Expr *OldInit = Pattern->getInClassInitializer();
|
|
|
|
if (!OldInit) {
|
|
|
|
RecordDecl *PatternRD = Pattern->getParent();
|
|
|
|
RecordDecl *OutermostClass = PatternRD->getOuterLexicalRecordContext();
|
2016-11-23 06:55:12 +08:00
|
|
|
Diag(PointOfInstantiation,
|
|
|
|
diag::err_in_class_initializer_not_yet_parsed)
|
|
|
|
<< OutermostClass << Pattern;
|
2018-08-10 05:09:38 +08:00
|
|
|
Diag(Pattern->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
|
2014-11-18 07:36:45 +08:00
|
|
|
Instantiation->setInvalidDecl();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
|
|
|
|
if (Inst.isInvalid())
|
|
|
|
return true;
|
2016-08-31 10:15:21 +08:00
|
|
|
if (Inst.isAlreadyInstantiating()) {
|
|
|
|
// Error out if we hit an instantiation cycle for this initializer.
|
|
|
|
Diag(PointOfInstantiation, diag::err_in_class_initializer_cycle)
|
|
|
|
<< Instantiation;
|
|
|
|
return true;
|
|
|
|
}
|
2018-03-23 08:07:18 +08:00
|
|
|
PrettyDeclStackTraceEntry CrashInfo(Context, Instantiation, SourceLocation(),
|
2016-05-27 04:23:13 +08:00
|
|
|
"instantiating default member init");
|
2014-11-18 07:36:45 +08:00
|
|
|
|
|
|
|
// Enter the scope of this instantiation. We don't use PushDeclContext because
|
|
|
|
// we don't have a scope.
|
|
|
|
ContextRAII SavedContext(*this, Instantiation->getParent());
|
2017-04-02 05:30:49 +08:00
|
|
|
EnterExpressionEvaluationContext EvalContext(
|
|
|
|
*this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
|
2014-11-18 07:36:45 +08:00
|
|
|
|
2015-04-29 01:58:47 +08:00
|
|
|
LocalInstantiationScope Scope(*this, true);
|
2014-11-18 07:36:45 +08:00
|
|
|
|
|
|
|
// Instantiate the initializer.
|
|
|
|
ActOnStartCXXInClassMemberInitializer();
|
2018-12-13 18:15:27 +08:00
|
|
|
CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers());
|
2014-11-18 07:36:45 +08:00
|
|
|
|
|
|
|
ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
|
|
|
|
/*CXXDirectInit=*/false);
|
|
|
|
Expr *Init = NewInit.get();
|
|
|
|
assert((!Init || !isa<ParenListExpr>(Init)) && "call-style init in class");
|
|
|
|
ActOnFinishCXXInClassMemberInitializer(
|
2018-08-10 05:08:08 +08:00
|
|
|
Instantiation, Init ? Init->getBeginLoc() : SourceLocation(), Init);
|
2014-11-18 07:36:45 +08:00
|
|
|
|
2016-08-25 05:25:37 +08:00
|
|
|
if (auto *L = getASTMutationListener())
|
|
|
|
L->DefaultMemberInitializerInstantiated(Instantiation);
|
|
|
|
|
2014-11-18 07:36:45 +08:00
|
|
|
// Return true if the in-class initializer is still missing.
|
|
|
|
return !Instantiation->getInClassInitializer();
|
|
|
|
}
|
|
|
|
|
2010-10-13 07:32:35 +08:00
|
|
|
namespace {
|
2018-05-09 09:00:01 +08:00
|
|
|
/// A partial specialization whose template arguments have matched
|
2010-10-13 07:32:35 +08:00
|
|
|
/// a given template-id.
|
|
|
|
struct PartialSpecMatchResult {
|
|
|
|
ClassTemplatePartialSpecializationDecl *Partial;
|
|
|
|
TemplateArgumentList *Args;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-06-07 10:42:27 +08:00
|
|
|
bool Sema::usesPartialOrExplicitSpecialization(
|
|
|
|
SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec) {
|
|
|
|
if (ClassTemplateSpec->getTemplateSpecializationKind() ==
|
|
|
|
TSK_ExplicitSpecialization)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
|
|
|
|
ClassTemplateSpec->getSpecializedTemplate()
|
|
|
|
->getPartialSpecializations(PartialSpecs);
|
|
|
|
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
|
|
|
|
TemplateDeductionInfo Info(Loc);
|
|
|
|
if (!DeduceTemplateArguments(PartialSpecs[I],
|
|
|
|
ClassTemplateSpec->getTemplateArgs(), Info))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-09 06:45:21 +08:00
|
|
|
/// Get the instantiation pattern to use to instantiate the definition of a
|
|
|
|
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
|
|
|
|
/// template or of a partial specialization).
|
|
|
|
static CXXRecordDecl *
|
|
|
|
getPatternForClassTemplateSpecialization(
|
|
|
|
Sema &S, SourceLocation PointOfInstantiation,
|
2013-08-22 08:59:14 +08:00
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
TemplateSpecializationKind TSK, bool Complain) {
|
2017-01-09 06:45:21 +08:00
|
|
|
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
|
|
|
|
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
|
|
|
|
return nullptr;
|
|
|
|
|
2018-05-17 02:28:58 +08:00
|
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
|
|
Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
|
|
|
|
if (!Specialized.is<ClassTemplatePartialSpecializationDecl *>()) {
|
|
|
|
// Find best matching specialization.
|
|
|
|
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
|
|
|
|
|
|
|
// C++ [temp.class.spec.match]p1:
|
|
|
|
// When a class template is used in a context that requires an
|
|
|
|
// instantiation of the class, it is necessary to determine
|
|
|
|
// whether the instantiation is to be generated using the primary
|
|
|
|
// template or one of the partial specializations. This is done by
|
|
|
|
// matching the template arguments of the class template
|
|
|
|
// specialization with the template argument lists of the partial
|
|
|
|
// specializations.
|
|
|
|
typedef PartialSpecMatchResult MatchResult;
|
|
|
|
SmallVector<MatchResult, 4> Matched;
|
|
|
|
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
|
|
|
|
Template->getPartialSpecializations(PartialSpecs);
|
|
|
|
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
|
|
|
|
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
|
|
|
|
ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
|
|
|
|
TemplateDeductionInfo Info(FailedCandidates.getLocation());
|
|
|
|
if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(
|
|
|
|
Partial, ClassTemplateSpec->getTemplateArgs(), Info)) {
|
|
|
|
// Store the failed-deduction information for use in diagnostics, later.
|
|
|
|
// TODO: Actually use the failed-deduction info?
|
|
|
|
FailedCandidates.addCandidate().set(
|
|
|
|
DeclAccessPair::make(Template, AS_public), Partial,
|
|
|
|
MakeDeductionFailureInfo(S.Context, Result, Info));
|
|
|
|
(void)Result;
|
|
|
|
} else {
|
|
|
|
Matched.push_back(PartialSpecMatchResult());
|
|
|
|
Matched.back().Partial = Partial;
|
|
|
|
Matched.back().Args = Info.take();
|
|
|
|
}
|
2009-06-13 02:26:56 +08:00
|
|
|
}
|
2009-05-31 17:31:02 +08:00
|
|
|
|
2018-05-17 02:28:58 +08:00
|
|
|
// If we're dealing with a member template where the template parameters
|
|
|
|
// have been instantiated, this provides the original template parameters
|
|
|
|
// from which the member template's parameters were instantiated.
|
2013-11-27 13:22:15 +08:00
|
|
|
|
2018-05-17 02:28:58 +08:00
|
|
|
if (Matched.size() >= 1) {
|
|
|
|
SmallVectorImpl<MatchResult>::iterator Best = Matched.begin();
|
|
|
|
if (Matched.size() == 1) {
|
|
|
|
// -- If exactly one matching specialization is found, the
|
|
|
|
// instantiation is generated from that specialization.
|
|
|
|
// We don't need to do anything for this.
|
|
|
|
} else {
|
|
|
|
// -- If more than one matching specialization is found, the
|
|
|
|
// partial order rules (14.5.4.2) are used to determine
|
|
|
|
// whether one of the specializations is more specialized
|
|
|
|
// than the others. If none of the specializations is more
|
|
|
|
// specialized than all of the other matching
|
|
|
|
// specializations, then the use of the class template is
|
|
|
|
// ambiguous and the program is ill-formed.
|
|
|
|
for (SmallVectorImpl<MatchResult>::iterator P = Best + 1,
|
|
|
|
PEnd = Matched.end();
|
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (S.getMoreSpecializedPartialSpecialization(
|
|
|
|
P->Partial, Best->Partial, PointOfInstantiation) ==
|
|
|
|
P->Partial)
|
|
|
|
Best = P;
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
2018-05-17 02:28:58 +08:00
|
|
|
|
|
|
|
// Determine if the best partial specialization is more specialized than
|
|
|
|
// the others.
|
|
|
|
bool Ambiguous = false;
|
2013-07-04 11:08:24 +08:00
|
|
|
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
|
|
|
|
PEnd = Matched.end();
|
2018-05-17 02:28:58 +08:00
|
|
|
P != PEnd; ++P) {
|
|
|
|
if (P != Best && S.getMoreSpecializedPartialSpecialization(
|
|
|
|
P->Partial, Best->Partial,
|
|
|
|
PointOfInstantiation) != Best->Partial) {
|
|
|
|
Ambiguous = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Ambiguous) {
|
|
|
|
// Partial ordering did not produce a clear winner. Complain.
|
|
|
|
Inst.Clear();
|
|
|
|
ClassTemplateSpec->setInvalidDecl();
|
|
|
|
S.Diag(PointOfInstantiation,
|
|
|
|
diag::err_partial_spec_ordering_ambiguous)
|
|
|
|
<< ClassTemplateSpec;
|
|
|
|
|
|
|
|
// Print the matching partial specializations.
|
|
|
|
for (SmallVectorImpl<MatchResult>::iterator P = Matched.begin(),
|
|
|
|
PEnd = Matched.end();
|
|
|
|
P != PEnd; ++P)
|
|
|
|
S.Diag(P->Partial->getLocation(), diag::note_partial_spec_match)
|
|
|
|
<< S.getTemplateArgumentBindingsText(
|
|
|
|
P->Partial->getTemplateParameters(), *P->Args);
|
2009-10-29 08:04:11 +08:00
|
|
|
|
2018-05-17 02:28:58 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
2018-05-17 02:28:58 +08:00
|
|
|
|
|
|
|
ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args);
|
|
|
|
} else {
|
|
|
|
// -- If no matches are found, the instantiation is generated
|
|
|
|
// from the primary template.
|
2009-09-16 00:23:51 +08:00
|
|
|
}
|
2018-05-17 02:28:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CXXRecordDecl *Pattern = nullptr;
|
|
|
|
Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
|
|
|
|
if (auto *PartialSpec =
|
|
|
|
Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
|
2009-09-16 00:23:51 +08:00
|
|
|
// Instantiate using the best class template partial specialization.
|
2018-05-17 02:28:58 +08:00
|
|
|
while (PartialSpec->getInstantiatedFromMember()) {
|
2009-10-29 08:04:11 +08:00
|
|
|
// If we've found an explicit specialization of this class template,
|
|
|
|
// stop here and use that as the pattern.
|
2018-05-17 02:28:58 +08:00
|
|
|
if (PartialSpec->isMemberSpecialization())
|
2009-10-29 08:04:11 +08:00
|
|
|
break;
|
2018-05-17 02:28:58 +08:00
|
|
|
|
|
|
|
PartialSpec = PartialSpec->getInstantiatedFromMember();
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
2018-05-17 02:28:58 +08:00
|
|
|
Pattern = PartialSpec;
|
2009-06-13 06:31:52 +08:00
|
|
|
} else {
|
2018-05-17 02:28:58 +08:00
|
|
|
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
|
|
|
while (Template->getInstantiatedFromMemberTemplate()) {
|
2009-10-14 00:30:37 +08:00
|
|
|
// If we've found an explicit specialization of this class template,
|
|
|
|
// stop here and use that as the pattern.
|
2018-05-17 02:28:58 +08:00
|
|
|
if (Template->isMemberSpecialization())
|
2009-10-14 00:30:37 +08:00
|
|
|
break;
|
2018-05-17 02:28:58 +08:00
|
|
|
|
|
|
|
Template = Template->getInstantiatedFromMemberTemplate();
|
2009-10-14 00:30:37 +08:00
|
|
|
}
|
2018-05-17 02:28:58 +08:00
|
|
|
Pattern = Template->getTemplatedDecl();
|
2009-05-31 17:31:02 +08:00
|
|
|
}
|
2009-03-26 05:17:03 +08:00
|
|
|
|
2017-01-09 06:45:21 +08:00
|
|
|
return Pattern;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2017-01-09 06:45:21 +08:00
|
|
|
bool Sema::InstantiateClassTemplateSpecialization(
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
TemplateSpecializationKind TSK, bool Complain) {
|
|
|
|
// Perform the actual instantiation on the canonical declaration.
|
|
|
|
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
|
|
|
ClassTemplateSpec->getCanonicalDecl());
|
|
|
|
if (ClassTemplateSpec->isInvalidDecl())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
CXXRecordDecl *Pattern = getPatternForClassTemplateSpecialization(
|
|
|
|
*this, PointOfInstantiation, ClassTemplateSpec, TSK, Complain);
|
|
|
|
if (!Pattern)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, Pattern,
|
|
|
|
getTemplateInstantiationArgs(ClassTemplateSpec), TSK,
|
|
|
|
Complain);
|
2009-03-26 05:17:03 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Instantiates the definitions of all of the member
|
2009-08-26 06:02:44 +08:00
|
|
|
/// of the given class, which is an instantiation of a class template
|
|
|
|
/// or a member class of a template.
|
2009-05-14 04:28:22 +08:00
|
|
|
void
|
|
|
|
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
2009-09-05 06:48:11 +08:00
|
|
|
CXXRecordDecl *Instantiation,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
|
|
|
TemplateSpecializationKind TSK) {
|
2014-04-25 06:45:46 +08:00
|
|
|
// FIXME: We need to notify the ASTMutationListener that we did all of these
|
|
|
|
// things, in case we have an explicit instantiation definition in a PCM, a
|
|
|
|
// module, or preamble, and the declaration is in an imported AST.
|
2013-11-27 16:20:38 +08:00
|
|
|
assert(
|
|
|
|
(TSK == TSK_ExplicitInstantiationDefinition ||
|
|
|
|
TSK == TSK_ExplicitInstantiationDeclaration ||
|
|
|
|
(TSK == TSK_ImplicitInstantiation && Instantiation->isLocalClass())) &&
|
|
|
|
"Unexpected template specialization kind!");
|
2014-03-08 03:56:05 +08:00
|
|
|
for (auto *D : Instantiation->decls()) {
|
2009-10-28 02:42:08 +08:00
|
|
|
bool SuppressNew = false;
|
2014-03-08 03:56:05 +08:00
|
|
|
if (auto *Function = dyn_cast<FunctionDecl>(D)) {
|
2018-10-04 23:49:42 +08:00
|
|
|
if (FunctionDecl *Pattern =
|
|
|
|
Function->getInstantiatedFromMemberFunction()) {
|
|
|
|
|
|
|
|
if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MemberSpecializationInfo *MSInfo =
|
|
|
|
Function->getMemberSpecializationInfo();
|
2009-10-28 02:42:08 +08:00
|
|
|
assert(MSInfo && "No member specialization information?");
|
2010-04-10 05:02:29 +08:00
|
|
|
if (MSInfo->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitSpecialization)
|
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
|
|
|
|
Function,
|
2009-10-28 02:42:08 +08:00
|
|
|
MSInfo->getTemplateSpecializationKind(),
|
2010-09-28 05:02:09 +08:00
|
|
|
MSInfo->getPointOfInstantiation(),
|
2009-10-28 02:42:08 +08:00
|
|
|
SuppressNew) ||
|
|
|
|
SuppressNew)
|
2009-10-08 23:14:33 +08:00
|
|
|
continue;
|
2014-04-25 06:45:46 +08:00
|
|
|
|
|
|
|
// C++11 [temp.explicit]p8:
|
|
|
|
// An explicit instantiation definition that names a class template
|
|
|
|
// specialization explicitly instantiates the class template
|
|
|
|
// specialization and is only an explicit instantiation definition
|
|
|
|
// of members whose definition is visible at the point of
|
|
|
|
// instantiation.
|
|
|
|
if (TSK == TSK_ExplicitInstantiationDefinition && !Pattern->isDefined())
|
2009-10-28 02:42:08 +08:00
|
|
|
continue;
|
|
|
|
|
2014-04-25 06:45:46 +08:00
|
|
|
Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
|
|
|
|
|
|
|
if (Function->isDefined()) {
|
|
|
|
// Let the ASTConsumer know that this function has been explicitly
|
|
|
|
// instantiated now, and its linkage might have changed.
|
|
|
|
Consumer.HandleTopLevelDecl(DeclGroupRef(Function));
|
|
|
|
} else if (TSK == TSK_ExplicitInstantiationDefinition) {
|
2009-10-28 02:42:08 +08:00
|
|
|
InstantiateFunctionDefinition(PointOfInstantiation, Function);
|
2014-04-25 06:45:46 +08:00
|
|
|
} else if (TSK == TSK_ImplicitInstantiation) {
|
|
|
|
PendingLocalImplicitInstantiations.push_back(
|
|
|
|
std::make_pair(Function, PointOfInstantiation));
|
2009-10-28 02:42:08 +08:00
|
|
|
}
|
2009-10-08 23:14:33 +08:00
|
|
|
}
|
2014-03-08 03:56:05 +08:00
|
|
|
} else if (auto *Var = dyn_cast<VarDecl>(D)) {
|
2013-09-28 04:14:12 +08:00
|
|
|
if (isa<VarTemplateSpecializationDecl>(Var))
|
|
|
|
continue;
|
|
|
|
|
2009-10-08 15:24:58 +08:00
|
|
|
if (Var->isStaticDataMember()) {
|
2018-10-04 23:49:42 +08:00
|
|
|
if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
|
|
|
|
continue;
|
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
|
|
|
|
assert(MSInfo && "No member specialization information?");
|
2010-04-10 05:02:29 +08:00
|
|
|
if (MSInfo->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitSpecialization)
|
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
|
|
|
|
Var,
|
2009-10-28 02:42:08 +08:00
|
|
|
MSInfo->getTemplateSpecializationKind(),
|
2010-09-28 05:02:09 +08:00
|
|
|
MSInfo->getPointOfInstantiation(),
|
2009-10-28 02:42:08 +08:00
|
|
|
SuppressNew) ||
|
|
|
|
SuppressNew)
|
2009-10-08 23:14:33 +08:00
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
if (TSK == TSK_ExplicitInstantiationDefinition) {
|
|
|
|
// C++0x [temp.explicit]p8:
|
|
|
|
// An explicit instantiation definition that names a class template
|
2018-07-31 03:24:48 +08:00
|
|
|
// specialization explicitly instantiates the class template
|
|
|
|
// specialization and is only an explicit instantiation definition
|
|
|
|
// of members whose definition is visible at the point of
|
2009-10-28 02:42:08 +08:00
|
|
|
// instantiation.
|
2016-06-25 08:15:56 +08:00
|
|
|
if (!Var->getInstantiatedFromStaticDataMember()->getDefinition())
|
2009-10-28 02:42:08 +08:00
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
2017-12-05 09:31:47 +08:00
|
|
|
InstantiateVariableDefinition(PointOfInstantiation, Var);
|
2009-10-28 02:42:08 +08:00
|
|
|
} else {
|
|
|
|
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
}
|
2014-03-08 03:56:05 +08:00
|
|
|
} else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
|
2018-10-04 23:49:42 +08:00
|
|
|
if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
|
|
|
|
continue;
|
|
|
|
|
2010-04-19 02:11:38 +08:00
|
|
|
// Always skip the injected-class-name, along with any
|
|
|
|
// redeclarations of nested classes, since both would cause us
|
|
|
|
// to try to instantiate the members of a class twice.
|
2014-11-21 06:56:34 +08:00
|
|
|
// Skip closure types; they'll get instantiated when we instantiate
|
|
|
|
// the corresponding lambda-expression.
|
|
|
|
if (Record->isInjectedClassName() || Record->getPreviousDecl() ||
|
|
|
|
Record->isLambda())
|
2009-10-08 07:56:10 +08:00
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
|
|
|
|
assert(MSInfo && "No member specialization information?");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-04-10 05:02:29 +08:00
|
|
|
if (MSInfo->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitSpecialization)
|
|
|
|
continue;
|
2010-09-28 05:02:09 +08:00
|
|
|
|
2019-04-30 05:32:05 +08:00
|
|
|
if (Context.getTargetInfo().getTriple().isOSWindows() &&
|
2016-05-27 03:42:56 +08:00
|
|
|
TSK == TSK_ExplicitInstantiationDeclaration) {
|
2019-04-30 05:32:05 +08:00
|
|
|
// On Windows, explicit instantiation decl of the outer class doesn't
|
|
|
|
// affect the inner class. Typically extern template declarations are
|
|
|
|
// used in combination with dll import/export annotations, but those
|
|
|
|
// are not propagated from the outer class templates to inner classes.
|
|
|
|
// Therefore, do not instantiate inner classes on this platform, so
|
|
|
|
// that users don't end up with undefined symbols during linking.
|
2016-05-27 03:42:56 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
|
|
|
|
Record,
|
2009-10-28 02:42:08 +08:00
|
|
|
MSInfo->getTemplateSpecializationKind(),
|
2010-09-28 05:02:09 +08:00
|
|
|
MSInfo->getPointOfInstantiation(),
|
2009-10-28 02:42:08 +08:00
|
|
|
SuppressNew) ||
|
|
|
|
SuppressNew)
|
2009-10-08 23:14:33 +08:00
|
|
|
continue;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
|
|
|
|
assert(Pattern && "Missing instantiated-from-template information");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-02-11 09:04:33 +08:00
|
|
|
if (!Record->getDefinition()) {
|
|
|
|
if (!Pattern->getDefinition()) {
|
2009-10-28 02:42:08 +08:00
|
|
|
// C++0x [temp.explicit]p8:
|
|
|
|
// An explicit instantiation definition that names a class template
|
2018-07-31 03:24:48 +08:00
|
|
|
// specialization explicitly instantiates the class template
|
|
|
|
// specialization and is only an explicit instantiation definition
|
|
|
|
// of members whose definition is visible at the point of
|
2009-10-28 02:42:08 +08:00
|
|
|
// instantiation.
|
|
|
|
if (TSK == TSK_ExplicitInstantiationDeclaration) {
|
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
|
|
|
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
continue;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
InstantiateClass(PointOfInstantiation, Record, Pattern,
|
2009-09-05 06:48:11 +08:00
|
|
|
TemplateArgs,
|
|
|
|
TSK);
|
2010-09-28 05:02:09 +08:00
|
|
|
} else {
|
|
|
|
if (TSK == TSK_ExplicitInstantiationDefinition &&
|
|
|
|
Record->getTemplateSpecializationKind() ==
|
|
|
|
TSK_ExplicitInstantiationDeclaration) {
|
|
|
|
Record->setTemplateSpecializationKind(TSK);
|
|
|
|
MarkVTableUsed(PointOfInstantiation, Record, true);
|
|
|
|
}
|
2009-10-28 02:42:08 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-02-11 09:04:33 +08:00
|
|
|
Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition());
|
2009-10-28 02:42:08 +08:00
|
|
|
if (Pattern)
|
2018-07-31 03:24:48 +08:00
|
|
|
InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
|
2009-10-28 02:42:08 +08:00
|
|
|
TSK);
|
2014-03-08 03:56:05 +08:00
|
|
|
} else if (auto *Enum = dyn_cast<EnumDecl>(D)) {
|
2012-03-15 07:13:10 +08:00
|
|
|
MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo();
|
|
|
|
assert(MSInfo && "No member specialization information?");
|
|
|
|
|
|
|
|
if (MSInfo->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitSpecialization)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (CheckSpecializationInstantiationRedecl(
|
|
|
|
PointOfInstantiation, TSK, Enum,
|
|
|
|
MSInfo->getTemplateSpecializationKind(),
|
|
|
|
MSInfo->getPointOfInstantiation(), SuppressNew) ||
|
|
|
|
SuppressNew)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (Enum->getDefinition())
|
|
|
|
continue;
|
|
|
|
|
2016-05-05 08:56:12 +08:00
|
|
|
EnumDecl *Pattern = Enum->getTemplateInstantiationPattern();
|
2012-03-15 07:13:10 +08:00
|
|
|
assert(Pattern && "Missing instantiated-from-template information");
|
|
|
|
|
|
|
|
if (TSK == TSK_ExplicitInstantiationDefinition) {
|
|
|
|
if (!Pattern->getDefinition())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK);
|
|
|
|
} else {
|
|
|
|
MSInfo->setTemplateSpecializationKind(TSK);
|
|
|
|
MSInfo->setPointOfInstantiation(PointOfInstantiation);
|
|
|
|
}
|
2014-11-18 07:36:45 +08:00
|
|
|
} else if (auto *Field = dyn_cast<FieldDecl>(D)) {
|
|
|
|
// No need to instantiate in-class initializers during explicit
|
|
|
|
// instantiation.
|
|
|
|
if (Field->hasInClassInitializer() && TSK == TSK_ImplicitInstantiation) {
|
|
|
|
CXXRecordDecl *ClassPattern =
|
|
|
|
Instantiation->getTemplateInstantiationPattern();
|
|
|
|
DeclContext::lookup_result Lookup =
|
|
|
|
ClassPattern->lookup(Field->getDeclName());
|
2016-06-09 13:26:56 +08:00
|
|
|
FieldDecl *Pattern = cast<FieldDecl>(Lookup.front());
|
2014-11-18 07:36:45 +08:00
|
|
|
InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern,
|
|
|
|
TemplateArgs);
|
|
|
|
}
|
2009-05-14 04:28:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Instantiate the definitions of all of the members of the
|
2009-05-14 04:28:22 +08:00
|
|
|
/// given class template specialization, which was named as part of an
|
|
|
|
/// explicit instantiation.
|
2009-09-09 23:08:12 +08:00
|
|
|
void
|
2009-09-05 06:48:11 +08:00
|
|
|
Sema::InstantiateClassTemplateSpecializationMembers(
|
2009-05-14 04:28:22 +08:00
|
|
|
SourceLocation PointOfInstantiation,
|
2009-09-05 06:48:11 +08:00
|
|
|
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
|
|
|
TemplateSpecializationKind TSK) {
|
2009-05-14 04:28:22 +08:00
|
|
|
// C++0x [temp.explicit]p7:
|
|
|
|
// An explicit instantiation that names a class template
|
|
|
|
// specialization is an explicit instantion of the same kind
|
|
|
|
// (declaration or definition) of each of its members (not
|
|
|
|
// including members inherited from base classes) that has not
|
|
|
|
// been previously explicitly specialized in the translation unit
|
|
|
|
// containing the explicit instantiation, except as described
|
|
|
|
// below.
|
|
|
|
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
|
2009-09-05 06:48:11 +08:00
|
|
|
getTemplateInstantiationArgs(ClassTemplateSpec),
|
|
|
|
TSK);
|
2009-05-14 04:28:22 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
StmtResult
|
2009-08-29 04:31:08 +08:00
|
|
|
Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-08-20 15:17:43 +08:00
|
|
|
if (!S)
|
2014-05-29 22:05:12 +08:00
|
|
|
return S;
|
2009-08-20 15:17:43 +08:00
|
|
|
|
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs,
|
|
|
|
SourceLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformStmt(S);
|
|
|
|
}
|
|
|
|
|
2019-12-23 14:37:35 +08:00
|
|
|
bool Sema::SubstTemplateArguments(
|
|
|
|
ArrayRef<TemplateArgumentLoc> Args,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
|
|
|
TemplateArgumentListInfo &Out) {
|
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs,
|
|
|
|
SourceLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(),
|
|
|
|
Out);
|
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2009-08-29 04:31:08 +08:00
|
|
|
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-08-11 13:31:07 +08:00
|
|
|
if (!E)
|
2014-05-29 22:05:12 +08:00
|
|
|
return E;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-11 13:31:07 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs,
|
|
|
|
SourceLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformExpr(E);
|
|
|
|
}
|
|
|
|
|
2012-12-19 09:39:02 +08:00
|
|
|
ExprResult Sema::SubstInitializer(Expr *Init,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
|
|
|
bool CXXDirectInit) {
|
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs,
|
|
|
|
SourceLocation(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformInitializer(Init, CXXDirectInit);
|
|
|
|
}
|
|
|
|
|
2015-12-25 07:58:29 +08:00
|
|
|
bool Sema::SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
|
2011-01-08 03:35:17 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<Expr *> &Outputs) {
|
2015-12-25 07:58:29 +08:00
|
|
|
if (Exprs.empty())
|
2011-01-08 03:35:17 +08:00
|
|
|
return false;
|
2012-12-19 09:39:02 +08:00
|
|
|
|
2011-01-08 03:35:17 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs,
|
|
|
|
SourceLocation(),
|
|
|
|
DeclarationName());
|
2015-12-25 07:58:29 +08:00
|
|
|
return Instantiator.TransformExprs(Exprs.data(), Exprs.size(),
|
|
|
|
IsCall, Outputs);
|
2011-01-08 03:35:17 +08:00
|
|
|
}
|
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NestedNameSpecifierLoc
|
|
|
|
Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
|
2018-07-31 03:24:48 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2011-02-25 10:25:35 +08:00
|
|
|
if (!NNS)
|
|
|
|
return NestedNameSpecifierLoc();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(),
|
|
|
|
DeclarationName());
|
|
|
|
return Instantiator.TransformNestedNameSpecifierLoc(NNS);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Do template substitution on declaration name info.
|
2010-08-12 06:01:17 +08:00
|
|
|
DeclarationNameInfo
|
|
|
|
Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(),
|
|
|
|
NameInfo.getName());
|
|
|
|
return Instantiator.TransformDeclarationNameInfo(NameInfo);
|
|
|
|
}
|
|
|
|
|
2009-04-01 02:38:02 +08:00
|
|
|
TemplateName
|
2011-03-03 02:46:51 +08:00
|
|
|
Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc,
|
|
|
|
TemplateName Name, SourceLocation Loc,
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-08-06 14:41:21 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
|
|
|
|
DeclarationName());
|
2011-03-03 02:46:51 +08:00
|
|
|
CXXScopeSpec SS;
|
|
|
|
SS.Adopt(QualifierLoc);
|
|
|
|
return Instantiator.TransformTemplateName(SS, Name, Loc);
|
2009-04-01 02:38:02 +08:00
|
|
|
}
|
2009-06-11 08:06:24 +08:00
|
|
|
|
2010-12-23 05:19:48 +08:00
|
|
|
bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
|
|
|
|
TemplateArgumentListInfo &Result,
|
2009-10-29 16:12:44 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-08-05 06:27:00 +08:00
|
|
|
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
|
|
|
|
DeclarationName());
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-23 05:19:48 +08:00
|
|
|
return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
|
2009-06-11 08:06:24 +08:00
|
|
|
}
|
2010-05-01 02:55:50 +08:00
|
|
|
|
2015-01-09 09:19:56 +08:00
|
|
|
static const Decl *getCanonicalParmVarDecl(const Decl *D) {
|
2012-09-27 01:57:31 +08:00
|
|
|
// When storing ParmVarDecls in the local instantiation scope, we always
|
|
|
|
// want to use the ParmVarDecl from the canonical function declaration,
|
|
|
|
// since the map is then valid for any redeclaration or definition of that
|
|
|
|
// function.
|
|
|
|
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D)) {
|
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
|
|
|
|
unsigned i = PV->getFunctionScopeIndex();
|
2015-01-09 09:19:56 +08:00
|
|
|
// This parameter might be from a freestanding function type within the
|
|
|
|
// function and isn't necessarily referring to one of FD's parameters.
|
2019-04-11 04:25:07 +08:00
|
|
|
if (i < FD->getNumParams() && FD->getParamDecl(i) == PV)
|
2015-01-09 09:19:56 +08:00
|
|
|
return FD->getCanonicalDecl()->getParamDecl(i);
|
2012-09-27 01:57:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return D;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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-08 00:43:16 +08:00
|
|
|
llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> *
|
|
|
|
LocalInstantiationScope::findInstantiationOf(const Decl *D) {
|
2012-09-27 01:57:31 +08:00
|
|
|
D = getCanonicalParmVarDecl(D);
|
2011-02-18 04:34:02 +08:00
|
|
|
for (LocalInstantiationScope *Current = this; Current;
|
2010-05-01 02:55:50 +08:00
|
|
|
Current = Current->Outer) {
|
2011-02-18 04:34:02 +08:00
|
|
|
|
2010-05-01 02:55:50 +08:00
|
|
|
// Check if we found something within this scope.
|
2010-12-22 05:22:51 +08:00
|
|
|
const Decl *CheckD = D;
|
|
|
|
do {
|
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-08 00:43:16 +08:00
|
|
|
LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD);
|
2010-12-22 05:22:51 +08:00
|
|
|
if (Found != Current->LocalDecls.end())
|
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-08 00:43:16 +08:00
|
|
|
return &Found->second;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2010-12-22 05:22:51 +08:00
|
|
|
// If this is a tag declaration, it's possible that we need to look for
|
|
|
|
// a previous declaration.
|
|
|
|
if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD))
|
2012-01-15 00:38:05 +08:00
|
|
|
CheckD = Tag->getPreviousDecl();
|
2010-12-22 05:22:51 +08:00
|
|
|
else
|
2014-05-26 14:22:03 +08:00
|
|
|
CheckD = nullptr;
|
2010-12-22 05:22:51 +08:00
|
|
|
} while (CheckD);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
// If we aren't combined with our outer scope, we're done.
|
2010-05-01 02:55:50 +08:00
|
|
|
if (!Current->CombineWithOuterScope)
|
|
|
|
break;
|
|
|
|
}
|
2011-02-18 04:34:02 +08:00
|
|
|
|
2013-07-15 14:14:07 +08:00
|
|
|
// If we're performing a partial substitution during template argument
|
|
|
|
// deduction, we may not have values for template parameters yet.
|
|
|
|
if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
|
|
|
|
isa<TemplateTemplateParmDecl>(D))
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2013-07-15 14:14:07 +08:00
|
|
|
|
2015-05-15 18:10:28 +08:00
|
|
|
// Local types referenced prior to definition may require instantiation.
|
|
|
|
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D))
|
|
|
|
if (RD->isLocalClass())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Enumeration types referenced prior to definition may appear as a result of
|
|
|
|
// error recovery.
|
|
|
|
if (isa<EnumDecl>(D))
|
2015-05-05 00:44:39 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
// If we didn't find the decl, then we either have a sema bug, or we have a
|
|
|
|
// forward reference to a label declaration. Return null to indicate that
|
|
|
|
// we have an uninstantiated label.
|
|
|
|
assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope");
|
2014-05-26 14:22:03 +08:00
|
|
|
return nullptr;
|
2010-05-01 02:55:50 +08:00
|
|
|
}
|
|
|
|
|
2010-08-25 13:32:35 +08:00
|
|
|
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
|
2012-09-27 01:57:31 +08:00
|
|
|
D = getCanonicalParmVarDecl(D);
|
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-08 00:43:16 +08:00
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
|
2015-01-09 09:19:56 +08:00
|
|
|
if (Stored.isNull()) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// It should not be present in any surrounding scope either.
|
|
|
|
LocalInstantiationScope *Current = this;
|
|
|
|
while (Current->CombineWithOuterScope && Current->Outer) {
|
|
|
|
Current = Current->Outer;
|
|
|
|
assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
|
|
|
|
"Instantiated local in inner and outer scopes");
|
|
|
|
}
|
|
|
|
#endif
|
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 15:32:04 +08:00
|
|
|
Stored = Inst;
|
2015-01-09 09:19:56 +08:00
|
|
|
} else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
|
2019-05-22 04:10:50 +08:00
|
|
|
Pack->push_back(cast<VarDecl>(Inst));
|
2015-01-09 09:19:56 +08:00
|
|
|
} else {
|
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 15:32:04 +08:00
|
|
|
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
|
2015-01-09 09:19:56 +08:00
|
|
|
}
|
2010-05-01 02:55:50 +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-08 00:43:16 +08:00
|
|
|
|
2015-09-30 22:04:23 +08:00
|
|
|
void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
|
2019-05-22 04:10:50 +08:00
|
|
|
VarDecl *Inst) {
|
2012-09-27 01:57:31 +08:00
|
|
|
D = getCanonicalParmVarDecl(D);
|
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-08 00:43:16 +08:00
|
|
|
DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
|
|
|
|
Pack->push_back(Inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
|
2015-01-09 09:19:56 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
// This should be the first time we've been told about this decl.
|
|
|
|
for (LocalInstantiationScope *Current = this;
|
|
|
|
Current && Current->CombineWithOuterScope; Current = Current->Outer)
|
|
|
|
assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
|
|
|
|
"Creating local pack after instantiation of local");
|
|
|
|
#endif
|
|
|
|
|
2012-09-27 01:57:31 +08:00
|
|
|
D = getCanonicalParmVarDecl(D);
|
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-08 00:43:16 +08:00
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
|
|
|
|
DeclArgumentPack *Pack = new DeclArgumentPack;
|
|
|
|
Stored = Pack;
|
|
|
|
ArgumentPacks.push_back(Pack);
|
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack,
|
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 15:32:04 +08:00
|
|
|
const TemplateArgument *ExplicitArgs,
|
|
|
|
unsigned NumExplicitArgs) {
|
|
|
|
assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
|
|
|
|
"Already have a partially-substituted pack");
|
2018-07-31 03:24:48 +08:00
|
|
|
assert((!PartiallySubstitutedPack
|
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 15:32:04 +08:00
|
|
|
|| NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
|
|
|
|
"Wrong number of arguments in partially-substituted pack");
|
|
|
|
PartiallySubstitutedPack = Pack;
|
|
|
|
ArgsInPartiallySubstitutedPack = ExplicitArgs;
|
|
|
|
NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
|
|
|
|
const TemplateArgument **ExplicitArgs,
|
|
|
|
unsigned *NumExplicitArgs) const {
|
|
|
|
if (ExplicitArgs)
|
2014-05-26 14:22:03 +08:00
|
|
|
*ExplicitArgs = nullptr;
|
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 15:32:04 +08:00
|
|
|
if (NumExplicitArgs)
|
|
|
|
*NumExplicitArgs = 0;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
for (const LocalInstantiationScope *Current = this; Current;
|
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 15:32:04 +08:00
|
|
|
Current = Current->Outer) {
|
|
|
|
if (Current->PartiallySubstitutedPack) {
|
|
|
|
if (ExplicitArgs)
|
|
|
|
*ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
|
|
|
|
if (NumExplicitArgs)
|
|
|
|
*NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
|
2018-07-31 03:24:48 +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 15:32:04 +08:00
|
|
|
return Current->PartiallySubstitutedPack;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Current->CombineWithOuterScope)
|
|
|
|
break;
|
|
|
|
}
|
2014-05-26 14:22:03 +08:00
|
|
|
|
|
|
|
return nullptr;
|
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 15:32:04 +08:00
|
|
|
}
|