2017-11-30 06:39:22 +08:00
|
|
|
//===- DeclTemplate.cpp - Template Declaration AST Node Implementation ----===//
|
2009-02-05 03:02:06 +08:00
|
|
|
//
|
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-05 03:02:06 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the C++ related Decl classes for templates.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/ASTMutationListener.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
2017-11-30 06:39:22 +08:00
|
|
|
#include "clang/AST/DeclarationName.h"
|
2009-02-10 02:46:07 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2018-03-30 04:51:59 +08:00
|
|
|
#include "clang/AST/ExternalASTSource.h"
|
2017-11-30 06:39:22 +08:00
|
|
|
#include "clang/AST/TemplateBase.h"
|
|
|
|
#include "clang/AST/TemplateName.h"
|
|
|
|
#include "clang/AST/Type.h"
|
2009-10-29 16:12:44 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2015-11-04 11:40:30 +08:00
|
|
|
#include "clang/Basic/Builtins.h"
|
2017-11-30 06:39:22 +08:00
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
|
|
#include "llvm/ADT/None.h"
|
|
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
2010-11-08 07:05:16 +08:00
|
|
|
#include <memory>
|
2017-11-30 06:39:22 +08:00
|
|
|
#include <utility>
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateParameterList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-07 06:42:48 +08:00
|
|
|
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
|
|
|
|
SourceLocation LAngleLoc,
|
2015-12-27 15:16:27 +08:00
|
|
|
ArrayRef<NamedDecl *> Params,
|
2016-07-31 06:33:34 +08:00
|
|
|
SourceLocation RAngleLoc,
|
|
|
|
Expr *RequiresClause)
|
2017-11-30 06:39:22 +08:00
|
|
|
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
|
|
|
|
NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
|
|
|
|
HasRequiresClause(static_cast<bool>(RequiresClause)) {
|
2012-09-07 10:06:42 +08:00
|
|
|
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
|
|
|
|
NamedDecl *P = Params[Idx];
|
|
|
|
begin()[Idx] = P;
|
|
|
|
|
|
|
|
if (!P->isTemplateParameterPack()) {
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
|
2012-09-07 10:06:42 +08:00
|
|
|
if (NTTP->getType()->containsUnexpandedParameterPack())
|
|
|
|
ContainsUnexpandedParameterPack = true;
|
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
|
2012-09-07 10:06:42 +08:00
|
|
|
if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
|
|
|
|
ContainsUnexpandedParameterPack = true;
|
|
|
|
|
|
|
|
// FIXME: If a default argument contains an unexpanded parameter pack, the
|
|
|
|
// template parameter list does too.
|
|
|
|
}
|
|
|
|
}
|
2016-07-31 06:33:34 +08:00
|
|
|
if (RequiresClause) {
|
|
|
|
*getTrailingObjects<Expr *>() = RequiresClause;
|
|
|
|
}
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2016-07-31 06:33:34 +08:00
|
|
|
TemplateParameterList *
|
|
|
|
TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
|
|
|
|
SourceLocation LAngleLoc,
|
|
|
|
ArrayRef<NamedDecl *> Params,
|
|
|
|
SourceLocation RAngleLoc, Expr *RequiresClause) {
|
|
|
|
void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>(
|
|
|
|
Params.size(), RequiresClause ? 1u : 0u),
|
2016-10-20 22:27:22 +08:00
|
|
|
alignof(TemplateParameterList));
|
2009-09-09 23:08:12 +08:00
|
|
|
return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
|
2016-07-31 06:33:34 +08:00
|
|
|
RAngleLoc, RequiresClause);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
unsigned TemplateParameterList::getMinRequiredArguments() const {
|
2011-01-20 04:10:05 +08:00
|
|
|
unsigned NumRequiredArgs = 0;
|
2016-07-06 12:19:16 +08:00
|
|
|
for (const NamedDecl *P : asArray()) {
|
|
|
|
if (P->isTemplateParameterPack()) {
|
|
|
|
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
|
2011-01-20 04:10:05 +08:00
|
|
|
if (NTTP->isExpandedParameterPack()) {
|
|
|
|
NumRequiredArgs += NTTP->getNumExpansionTypes();
|
|
|
|
continue;
|
|
|
|
}
|
2016-07-06 12:19:16 +08:00
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
break;
|
2011-01-20 04:10:05 +08:00
|
|
|
}
|
2016-07-06 12:19:16 +08:00
|
|
|
|
|
|
|
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
|
2011-01-20 04:10:05 +08:00
|
|
|
if (TTP->hasDefaultArgument())
|
|
|
|
break;
|
2016-07-06 12:19:16 +08:00
|
|
|
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
|
2011-01-20 04:10:05 +08:00
|
|
|
if (NTTP->hasDefaultArgument())
|
|
|
|
break;
|
2016-07-06 12:19:16 +08:00
|
|
|
} else if (cast<TemplateTemplateParmDecl>(P)->hasDefaultArgument())
|
2011-01-20 04:10:05 +08:00
|
|
|
break;
|
2016-07-06 12:19:16 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
++NumRequiredArgs;
|
2009-02-12 02:16:40 +08:00
|
|
|
}
|
2016-07-06 12:19:16 +08:00
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
return NumRequiredArgs;
|
|
|
|
}
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
unsigned TemplateParameterList::getDepth() const {
|
|
|
|
if (size() == 0)
|
|
|
|
return 0;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
const NamedDecl *FirstParm = getParam(0);
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(FirstParm))
|
2009-10-29 08:04:11 +08:00
|
|
|
return TTP->getDepth();
|
2018-03-30 04:51:59 +08:00
|
|
|
else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
|
2009-10-29 08:04:11 +08:00
|
|
|
return NTTP->getDepth();
|
|
|
|
else
|
|
|
|
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
|
|
|
|
}
|
|
|
|
|
2011-03-05 02:32:38 +08:00
|
|
|
static void AdoptTemplateParameterList(TemplateParameterList *Params,
|
|
|
|
DeclContext *Owner) {
|
2016-07-06 12:19:16 +08:00
|
|
|
for (NamedDecl *P : *Params) {
|
|
|
|
P->setDeclContext(Owner);
|
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-11 04:30:23 +08:00
|
|
|
namespace clang {
|
2017-11-30 06:39:22 +08:00
|
|
|
|
2015-06-11 04:30:23 +08:00
|
|
|
void *allocateDefaultArgStorageChain(const ASTContext &C) {
|
|
|
|
return new (C) char[sizeof(void*) * 2];
|
|
|
|
}
|
2017-11-30 06:39:22 +08:00
|
|
|
|
|
|
|
} // namespace clang
|
2015-06-11 04:30:23 +08:00
|
|
|
|
2010-07-30 00:11:51 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RedeclarableTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-12-29 10:02:30 +08:00
|
|
|
void RedeclarableTemplateDecl::anchor() {}
|
|
|
|
|
2013-01-24 00:52:57 +08:00
|
|
|
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
|
2013-10-19 10:28:17 +08:00
|
|
|
if (Common)
|
|
|
|
return Common;
|
2010-07-30 00:11:51 +08:00
|
|
|
|
2013-10-19 10:28:17 +08:00
|
|
|
// Walk the previous-declaration chain until we either find a declaration
|
|
|
|
// with a common pointer or we run out of previous declarations.
|
|
|
|
SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
|
|
|
|
for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
|
|
|
|
Prev = Prev->getPreviousDecl()) {
|
|
|
|
if (Prev->Common) {
|
|
|
|
Common = Prev->Common;
|
|
|
|
break;
|
2012-01-14 23:30:55 +08:00
|
|
|
}
|
2013-10-19 10:28:17 +08:00
|
|
|
|
|
|
|
PrevDecls.push_back(Prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we never found a common pointer, allocate one now.
|
|
|
|
if (!Common) {
|
|
|
|
// FIXME: If any of the declarations is from an AST file, we probably
|
|
|
|
// need an update record to add the common data.
|
|
|
|
|
|
|
|
Common = newCommon(getASTContext());
|
2010-07-30 00:12:01 +08:00
|
|
|
}
|
|
|
|
|
2013-10-19 10:28:17 +08:00
|
|
|
// Update any previous declarations we saw with the common pointer.
|
2016-07-06 12:19:16 +08:00
|
|
|
for (const RedeclarableTemplateDecl *Prev : PrevDecls)
|
|
|
|
Prev->Common = Common;
|
2013-10-19 10:28:17 +08:00
|
|
|
|
2012-01-14 23:13:49 +08:00
|
|
|
return Common;
|
2010-07-30 00:12:09 +08:00
|
|
|
}
|
|
|
|
|
2017-12-15 07:30:18 +08:00
|
|
|
void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
|
|
|
|
// Grab the most recent declaration to ensure we've loaded any lazy
|
|
|
|
// redeclarations of this template.
|
|
|
|
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
|
|
|
|
if (CommonBasePtr->LazySpecializations) {
|
|
|
|
ASTContext &Context = getASTContext();
|
|
|
|
uint32_t *Specs = CommonBasePtr->LazySpecializations;
|
|
|
|
CommonBasePtr->LazySpecializations = nullptr;
|
|
|
|
for (uint32_t I = 0, N = *Specs++; I != N; ++I)
|
|
|
|
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-24 09:23:23 +08:00
|
|
|
template<class EntryType>
|
|
|
|
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
|
2010-07-31 01:09:04 +08:00
|
|
|
RedeclarableTemplateDecl::findSpecializationImpl(
|
2015-02-24 09:23:23 +08:00
|
|
|
llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args,
|
|
|
|
void *&InsertPos) {
|
2017-11-30 06:39:22 +08:00
|
|
|
using SETraits = SpecEntryTraits<EntryType>;
|
|
|
|
|
2010-07-31 01:09:04 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
2017-12-15 07:30:18 +08:00
|
|
|
EntryType::Profile(ID, Args, getASTContext());
|
2010-07-31 01:09:04 +08:00
|
|
|
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
|
2015-02-24 09:23:23 +08:00
|
|
|
return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class Derived, class EntryType>
|
|
|
|
void RedeclarableTemplateDecl::addSpecializationImpl(
|
|
|
|
llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
|
|
|
|
void *InsertPos) {
|
2017-11-30 06:39:22 +08:00
|
|
|
using SETraits = SpecEntryTraits<EntryType>;
|
|
|
|
|
2015-02-24 09:23:23 +08:00
|
|
|
if (InsertPos) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
void *CorrectInsertPos;
|
|
|
|
assert(!findSpecializationImpl(Specializations,
|
|
|
|
SETraits::getTemplateArgs(Entry),
|
|
|
|
CorrectInsertPos) &&
|
|
|
|
InsertPos == CorrectInsertPos &&
|
|
|
|
"given incorrect InsertPos for specialization");
|
|
|
|
#endif
|
|
|
|
Specializations.InsertNode(Entry, InsertPos);
|
|
|
|
} else {
|
|
|
|
EntryType *Existing = Specializations.GetOrInsertNode(Entry);
|
|
|
|
(void)Existing;
|
|
|
|
assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
|
|
|
|
"non-canonical specialization?");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXTemplateSpecialization(cast<Derived>(this),
|
|
|
|
SETraits::getDecl(Entry));
|
2010-07-31 01:09:04 +08:00
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FunctionTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
2009-06-30 04:59:39 +08:00
|
|
|
TemplateParameterList *Params,
|
2009-02-05 03:02:06 +08:00
|
|
|
NamedDecl *Decl) {
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
|
2014-05-12 13:36:57 +08:00
|
|
|
DeclarationName(), nullptr, nullptr);
|
2011-03-05 01:52:15 +08:00
|
|
|
}
|
|
|
|
|
2010-09-09 03:31:22 +08:00
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
2013-01-24 00:52:57 +08:00
|
|
|
FunctionTemplateDecl::newCommon(ASTContext &C) const {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *CommonPtr = new (C) Common;
|
2017-02-14 13:37:36 +08:00
|
|
|
C.addDestruction(CommonPtr);
|
2010-07-30 00:11:51 +08:00
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
2013-06-28 12:37:53 +08:00
|
|
|
void FunctionTemplateDecl::LoadLazySpecializations() const {
|
2017-12-15 07:30:18 +08:00
|
|
|
loadLazySpecializationsImpl();
|
2013-06-28 12:37:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
|
|
|
|
FunctionTemplateDecl::getSpecializations() const {
|
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->Specializations;
|
|
|
|
}
|
|
|
|
|
2010-07-20 21:59:58 +08:00
|
|
|
FunctionDecl *
|
2014-06-26 12:58:53 +08:00
|
|
|
FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
|
|
|
|
void *&InsertPos) {
|
|
|
|
return findSpecializationImpl(getSpecializations(), Args, InsertPos);
|
2010-07-20 21:59:58 +08:00
|
|
|
}
|
|
|
|
|
2011-04-14 22:07:59 +08:00
|
|
|
void FunctionTemplateDecl::addSpecialization(
|
|
|
|
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
|
2015-02-24 09:23:23 +08:00
|
|
|
addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info,
|
|
|
|
InsertPos);
|
2011-04-14 22:07:59 +08:00
|
|
|
}
|
|
|
|
|
2013-05-17 11:04:50 +08:00
|
|
|
ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
|
2011-03-06 01:54:25 +08:00
|
|
|
TemplateParameterList *Params = getTemplateParameters();
|
|
|
|
Common *CommonPtr = getCommonPtr();
|
|
|
|
if (!CommonPtr->InjectedArgs) {
|
2016-12-23 10:10:11 +08:00
|
|
|
auto &Context = getASTContext();
|
|
|
|
SmallVector<TemplateArgument, 16> TemplateArgs;
|
|
|
|
Context.getInjectedTemplateArgs(Params, TemplateArgs);
|
|
|
|
CommonPtr->InjectedArgs =
|
|
|
|
new (Context) TemplateArgument[TemplateArgs.size()];
|
|
|
|
std::copy(TemplateArgs.begin(), TemplateArgs.end(),
|
|
|
|
CommonPtr->InjectedArgs);
|
2011-03-06 01:54:25 +08:00
|
|
|
}
|
2013-05-17 11:04:50 +08:00
|
|
|
|
|
|
|
return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size());
|
2011-03-06 01:54:25 +08:00
|
|
|
}
|
|
|
|
|
2018-10-11 01:17:51 +08:00
|
|
|
void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
|
|
|
|
using Base = RedeclarableTemplateDecl;
|
|
|
|
|
|
|
|
// If we haven't created a common pointer yet, then it can just be created
|
|
|
|
// with the usual method.
|
|
|
|
if (!Base::Common)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Common *ThisCommon = static_cast<Common *>(Base::Common);
|
|
|
|
Common *PrevCommon = nullptr;
|
|
|
|
SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
|
|
|
|
for (; Prev; Prev = Prev->getPreviousDecl()) {
|
|
|
|
if (Prev->Base::Common) {
|
|
|
|
PrevCommon = static_cast<Common *>(Prev->Base::Common);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
PreviousDecls.push_back(Prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the previous redecl chain hasn't created a common pointer yet, then just
|
|
|
|
// use this common pointer.
|
|
|
|
if (!PrevCommon) {
|
|
|
|
for (auto *D : PreviousDecls)
|
|
|
|
D->Base::Common = ThisCommon;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure we don't leak any important state.
|
|
|
|
assert(ThisCommon->Specializations.size() == 0 &&
|
|
|
|
"Can't merge incompatible declarations!");
|
|
|
|
|
|
|
|
Base::Common = PrevCommon;
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-06-20 03:29:09 +08:00
|
|
|
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
2017-02-10 10:46:19 +08:00
|
|
|
NamedDecl *Decl,
|
|
|
|
Expr *AssociatedConstraints) {
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
2017-02-10 10:46:19 +08:00
|
|
|
|
|
|
|
if (!AssociatedConstraints) {
|
|
|
|
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
|
|
|
|
}
|
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *const CTDI = new (C) ConstrainedTemplateDeclInfo;
|
|
|
|
auto *const New =
|
2017-02-10 10:46:19 +08:00
|
|
|
new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl);
|
|
|
|
New->setAssociatedConstraints(AssociatedConstraints);
|
2010-06-20 03:29:09 +08:00
|
|
|
return New;
|
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
|
|
|
}
|
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
|
|
|
|
DeclarationName(), nullptr, nullptr);
|
2011-03-05 01:52:15 +08:00
|
|
|
}
|
|
|
|
|
2013-02-14 21:20:36 +08:00
|
|
|
void ClassTemplateDecl::LoadLazySpecializations() const {
|
2017-12-15 07:30:18 +08:00
|
|
|
loadLazySpecializationsImpl();
|
2010-10-28 06:21:36 +08:00
|
|
|
}
|
|
|
|
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
|
2013-02-14 21:20:36 +08:00
|
|
|
ClassTemplateDecl::getSpecializations() const {
|
2010-10-28 06:21:36 +08:00
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->Specializations;
|
2018-07-31 03:24:48 +08:00
|
|
|
}
|
2010-10-28 06:21:36 +08:00
|
|
|
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
2010-10-28 06:21:36 +08:00
|
|
|
ClassTemplateDecl::getPartialSpecializations() {
|
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->PartialSpecializations;
|
2018-07-31 03:24:48 +08:00
|
|
|
}
|
2010-10-28 06:21:36 +08:00
|
|
|
|
2010-09-09 03:31:22 +08:00
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
2013-01-24 00:52:57 +08:00
|
|
|
ClassTemplateDecl::newCommon(ASTContext &C) const {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *CommonPtr = new (C) Common;
|
2017-02-14 13:37:36 +08:00
|
|
|
C.addDestruction(CommonPtr);
|
2010-07-30 00:11:51 +08:00
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
2010-07-20 21:59:28 +08:00
|
|
|
ClassTemplateSpecializationDecl *
|
2014-06-26 12:58:53 +08:00
|
|
|
ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
|
|
|
|
void *&InsertPos) {
|
|
|
|
return findSpecializationImpl(getSpecializations(), Args, InsertPos);
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
2010-10-28 15:38:42 +08:00
|
|
|
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
|
|
|
|
void *InsertPos) {
|
2015-02-24 09:23:23 +08:00
|
|
|
addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos);
|
2010-10-28 15:38:42 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 21:59:28 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
2014-06-26 12:58:53 +08:00
|
|
|
ClassTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
|
2010-07-20 21:59:28 +08:00
|
|
|
void *&InsertPos) {
|
2014-06-26 12:58:53 +08:00
|
|
|
return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos);
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
2010-10-28 15:38:42 +08:00
|
|
|
void ClassTemplateDecl::AddPartialSpecialization(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D,
|
|
|
|
void *InsertPos) {
|
2012-03-28 22:34:23 +08:00
|
|
|
if (InsertPos)
|
|
|
|
getPartialSpecializations().InsertNode(D, InsertPos);
|
|
|
|
else {
|
|
|
|
ClassTemplatePartialSpecializationDecl *Existing
|
|
|
|
= getPartialSpecializations().GetOrInsertNode(D);
|
|
|
|
(void)Existing;
|
|
|
|
assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
|
|
|
|
}
|
|
|
|
|
2010-10-28 15:38:42 +08:00
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXTemplateSpecialization(this, D);
|
|
|
|
}
|
|
|
|
|
2010-04-30 13:56:50 +08:00
|
|
|
void ClassTemplateDecl::getPartialSpecializations(
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
|
2012-05-04 07:49:05 +08:00
|
|
|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
|
2010-06-21 18:57:41 +08:00
|
|
|
= getPartialSpecializations();
|
2010-04-30 13:56:50 +08:00
|
|
|
PS.clear();
|
2013-08-23 07:27:37 +08:00
|
|
|
PS.reserve(PartialSpecs.size());
|
2016-07-06 12:19:16 +08:00
|
|
|
for (ClassTemplatePartialSpecializationDecl &P : PartialSpecs)
|
|
|
|
PS.push_back(P.getMostRecentDecl());
|
2010-04-30 13:56:50 +08:00
|
|
|
}
|
|
|
|
|
2009-07-31 01:40:51 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplateDecl::findPartialSpecialization(QualType T) {
|
|
|
|
ASTContext &Context = getASTContext();
|
2016-07-06 12:19:16 +08:00
|
|
|
for (ClassTemplatePartialSpecializationDecl &P :
|
|
|
|
getPartialSpecializations()) {
|
|
|
|
if (Context.hasSameType(P.getInjectedSpecializationType(), T))
|
|
|
|
return P.getMostRecentDecl();
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2010-07-20 21:59:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D) {
|
|
|
|
Decl *DCanon = D->getCanonicalDecl();
|
2016-07-06 12:19:16 +08:00
|
|
|
for (ClassTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
|
|
|
|
if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
|
|
|
|
return P.getMostRecentDecl();
|
2009-07-31 01:40:51 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2009-07-31 01:40:51 +08:00
|
|
|
}
|
|
|
|
|
2010-03-10 11:28:59 +08:00
|
|
|
QualType
|
2010-07-09 02:37:38 +08:00
|
|
|
ClassTemplateDecl::getInjectedClassNameSpecialization() {
|
2010-06-21 18:57:41 +08:00
|
|
|
Common *CommonPtr = getCommonPtr();
|
2009-05-11 06:57:19 +08:00
|
|
|
if (!CommonPtr->InjectedClassNameType.isNull())
|
|
|
|
return CommonPtr->InjectedClassNameType;
|
|
|
|
|
2010-12-24 00:00:30 +08:00
|
|
|
// C++0x [temp.dep.type]p2:
|
2018-07-31 03:24:48 +08:00
|
|
|
// The template argument list of a primary template is a template argument
|
2010-12-24 00:00:30 +08:00
|
|
|
// list in which the nth template argument has the value of the nth template
|
2018-07-31 03:24:48 +08:00
|
|
|
// parameter of the class template. If the nth template parameter is a
|
|
|
|
// template parameter pack (14.5.3), the nth template argument is a pack
|
|
|
|
// expansion (14.5.3) whose pattern is the name of the template parameter
|
2010-12-24 00:00:30 +08:00
|
|
|
// pack.
|
2010-07-09 02:37:38 +08:00
|
|
|
ASTContext &Context = getASTContext();
|
2009-05-11 06:57:19 +08:00
|
|
|
TemplateParameterList *Params = getTemplateParameters();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 16> TemplateArgs;
|
2016-12-23 10:10:11 +08:00
|
|
|
Context.getInjectedTemplateArgs(Params, TemplateArgs);
|
2009-05-11 06:57:19 +08:00
|
|
|
CommonPtr->InjectedClassNameType
|
2009-07-29 07:00:59 +08:00
|
|
|
= Context.getTemplateSpecializationType(TemplateName(this),
|
2016-07-07 12:43:07 +08:00
|
|
|
TemplateArgs);
|
2009-05-11 06:57:19 +08:00
|
|
|
return CommonPtr->InjectedClassNameType;
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateTypeParm Allocation/Deallocation Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2011-03-06 23:48:19 +08:00
|
|
|
SourceLocation KeyLoc, SourceLocation NameLoc,
|
|
|
|
unsigned D, unsigned P, IdentifierInfo *Id,
|
|
|
|
bool Typename, bool ParameterPack) {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *TTPDecl =
|
|
|
|
new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
|
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
|
|
|
QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
|
2014-04-24 02:20:42 +08:00
|
|
|
TTPDecl->setTypeForDecl(TTPType.getTypePtr());
|
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
|
|
|
return TTPDecl;
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-02 19:54:55 +08:00
|
|
|
TemplateTypeParmDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), nullptr, false);
|
2010-07-02 19:54:55 +08:00
|
|
|
}
|
|
|
|
|
2009-10-29 16:12:44 +08:00
|
|
|
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
|
2011-03-04 20:42:03 +08:00
|
|
|
return hasDefaultArgument()
|
2015-06-10 08:29:03 +08:00
|
|
|
? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc()
|
|
|
|
: SourceLocation();
|
2011-03-04 20:42:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange TemplateTypeParmDecl::getSourceRange() const {
|
|
|
|
if (hasDefaultArgument() && !defaultArgumentWasInherited())
|
2018-08-10 05:08:08 +08:00
|
|
|
return SourceRange(getBeginLoc(),
|
2015-06-10 08:29:03 +08:00
|
|
|
getDefaultArgumentInfo()->getTypeLoc().getEndLoc());
|
2011-03-04 20:42:03 +08:00
|
|
|
else
|
2011-03-06 23:48:19 +08:00
|
|
|
return TypeDecl::getSourceRange();
|
2009-10-29 16:12:44 +08:00
|
|
|
}
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
unsigned TemplateTypeParmDecl::getDepth() const {
|
2014-04-24 02:20:42 +08:00
|
|
|
return getTypeForDecl()->getAs<TemplateTypeParmType>()->getDepth();
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned TemplateTypeParmDecl::getIndex() const {
|
2014-04-24 02:20:42 +08:00
|
|
|
return getTypeForDecl()->getAs<TemplateTypeParmType>()->getIndex();
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
bool TemplateTypeParmDecl::isParameterPack() const {
|
2014-04-24 02:20:42 +08:00
|
|
|
return getTypeForDecl()->getAs<TemplateTypeParmType>()->isParameterPack();
|
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
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// NonTypeTemplateParmDecl Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-07-06 12:19:16 +08:00
|
|
|
NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
|
|
|
|
DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D,
|
|
|
|
unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
|
|
|
|
ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos)
|
|
|
|
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
|
|
|
|
TemplateParmPosition(D, P), ParameterPack(true),
|
|
|
|
ExpandedParameterPack(true), NumExpandedTypes(ExpandedTypes.size()) {
|
|
|
|
if (!ExpandedTypes.empty() && !ExpandedTInfos.empty()) {
|
2015-08-07 04:26:32 +08:00
|
|
|
auto TypesAndInfos =
|
|
|
|
getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
|
2011-01-20 04:10:05 +08:00
|
|
|
for (unsigned I = 0; I != NumExpandedTypes; ++I) {
|
2015-08-07 04:26:32 +08:00
|
|
|
new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]);
|
|
|
|
TypesAndInfos[I].second = ExpandedTInfos[I];
|
2011-01-20 04:10:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
NonTypeTemplateParmDecl *
|
2011-01-12 17:06:06 +08:00
|
|
|
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
|
|
|
unsigned D, unsigned P, IdentifierInfo *Id,
|
|
|
|
QualType T, bool ParameterPack,
|
|
|
|
TypeSourceInfo *TInfo) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id,
|
|
|
|
T, ParameterPack, TInfo);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2016-07-06 12:19:16 +08:00
|
|
|
NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
|
|
|
|
const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
|
|
|
|
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
|
|
|
|
ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
|
2015-08-07 04:26:32 +08:00
|
|
|
return new (C, DC,
|
|
|
|
additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
|
2016-07-06 12:19:16 +08:00
|
|
|
ExpandedTypes.size()))
|
2015-08-07 04:26:32 +08:00
|
|
|
NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
|
2016-07-06 12:19:16 +08:00
|
|
|
ExpandedTypes, ExpandedTInfos);
|
2011-01-20 04:10:05 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
NonTypeTemplateParmDecl *
|
|
|
|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) NonTypeTemplateParmDecl(nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), 0, 0, nullptr,
|
|
|
|
QualType(), false, nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
NonTypeTemplateParmDecl *
|
|
|
|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NumExpandedTypes) {
|
2016-07-06 12:19:16 +08:00
|
|
|
auto *NTTP =
|
|
|
|
new (C, ID, additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
|
|
|
|
NumExpandedTypes))
|
|
|
|
NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
|
|
|
|
0, 0, nullptr, QualType(), nullptr, None,
|
|
|
|
None);
|
|
|
|
NTTP->NumExpandedTypes = NumExpandedTypes;
|
|
|
|
return NTTP;
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2011-02-09 09:13:10 +08:00
|
|
|
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
|
2011-03-04 19:03:48 +08:00
|
|
|
if (hasDefaultArgument() && !defaultArgumentWasInherited())
|
2011-03-09 00:41:52 +08:00
|
|
|
return SourceRange(getOuterLocStart(),
|
|
|
|
getDefaultArgument()->getSourceRange().getEnd());
|
|
|
|
return DeclaratorDecl::getSourceRange();
|
2011-02-09 09:13:10 +08:00
|
|
|
}
|
|
|
|
|
2009-02-11 03:49:53 +08:00
|
|
|
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
|
2010-06-09 17:26:05 +08:00
|
|
|
return hasDefaultArgument()
|
|
|
|
? getDefaultArgument()->getSourceRange().getBegin()
|
|
|
|
: SourceLocation();
|
2009-02-11 03:49:53 +08:00
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateTemplateParmDecl Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-30 06:39:22 +08:00
|
|
|
void TemplateTemplateParmDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2012-09-07 10:06:42 +08:00
|
|
|
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
|
|
|
|
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id, TemplateParameterList *Params,
|
2016-07-06 12:19:16 +08:00
|
|
|
ArrayRef<TemplateParameterList *> Expansions)
|
|
|
|
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
|
|
|
|
TemplateParmPosition(D, P), ParameterPack(true),
|
|
|
|
ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) {
|
|
|
|
if (!Expansions.empty())
|
|
|
|
std::uninitialized_copy(Expansions.begin(), Expansions.end(),
|
2015-08-07 04:26:32 +08:00
|
|
|
getTrailingObjects<TemplateParameterList *>());
|
2012-09-07 10:06:42 +08:00
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
TemplateTemplateParmDecl *
|
2011-01-12 17:06:06 +08:00
|
|
|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
2009-02-05 03:02:06 +08:00
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
2011-01-05 23:48:55 +08:00
|
|
|
bool ParameterPack, IdentifierInfo *Id,
|
2009-02-05 03:02:06 +08:00
|
|
|
TemplateParameterList *Params) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
|
|
|
|
Params);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2012-09-07 10:06:42 +08:00
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id,
|
|
|
|
TemplateParameterList *Params,
|
2013-01-13 03:30:44 +08:00
|
|
|
ArrayRef<TemplateParameterList *> Expansions) {
|
2015-08-07 04:26:32 +08:00
|
|
|
return new (C, DC,
|
|
|
|
additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
|
2016-07-06 12:19:16 +08:00
|
|
|
TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions);
|
2012-09-07 10:06:42 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
2014-05-12 13:36:57 +08:00
|
|
|
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
|
|
|
|
false, nullptr, nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
|
|
|
|
2012-09-07 10:06:42 +08:00
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
|
|
|
|
unsigned NumExpansions) {
|
2016-07-06 12:19:16 +08:00
|
|
|
auto *TTP =
|
|
|
|
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
|
|
|
|
TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
|
|
|
|
nullptr, None);
|
|
|
|
TTP->NumExpandedParams = NumExpansions;
|
|
|
|
return TTP;
|
2012-09-07 10:06:42 +08:00
|
|
|
}
|
|
|
|
|
2015-06-18 04:16:32 +08:00
|
|
|
SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
|
|
|
|
return hasDefaultArgument() ? getDefaultArgument().getLocation()
|
|
|
|
: SourceLocation();
|
|
|
|
}
|
|
|
|
|
2015-06-10 08:29:03 +08:00
|
|
|
void TemplateTemplateParmDecl::setDefaultArgument(
|
|
|
|
const ASTContext &C, const TemplateArgumentLoc &DefArg) {
|
|
|
|
if (DefArg.getArgument().isNull())
|
|
|
|
DefaultArgument.set(nullptr);
|
|
|
|
else
|
|
|
|
DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
|
|
|
|
}
|
|
|
|
|
2009-05-12 07:53:27 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateArgumentList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2016-07-04 05:17:51 +08:00
|
|
|
TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args)
|
|
|
|
: Arguments(getTrailingObjects<TemplateArgument>()),
|
|
|
|
NumArguments(Args.size()) {
|
|
|
|
std::uninitialized_copy(Args.begin(), Args.end(),
|
2015-08-07 04:26:32 +08:00
|
|
|
getTrailingObjects<TemplateArgument>());
|
|
|
|
}
|
|
|
|
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgumentList *
|
|
|
|
TemplateArgumentList::CreateCopy(ASTContext &Context,
|
2016-07-04 05:17:51 +08:00
|
|
|
ArrayRef<TemplateArgument> Args) {
|
|
|
|
void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(Args.size()));
|
|
|
|
return new (Mem) TemplateArgumentList(Args);
|
2010-06-23 21:48:23 +08:00
|
|
|
}
|
|
|
|
|
2019-05-02 08:49:14 +08:00
|
|
|
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
|
|
|
|
ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
|
|
|
|
TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI,
|
|
|
|
MemberSpecializationInfo *MSInfo) {
|
2014-05-12 13:36:57 +08:00
|
|
|
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
|
2011-09-23 04:07:09 +08:00
|
|
|
if (TemplateArgsAsWritten)
|
|
|
|
ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
|
|
|
|
*TemplateArgsAsWritten);
|
|
|
|
|
2019-05-02 08:49:14 +08:00
|
|
|
void *Mem =
|
|
|
|
C.Allocate(totalSizeToAlloc<MemberSpecializationInfo *>(MSInfo ? 1 : 0));
|
|
|
|
return new (Mem) FunctionTemplateSpecializationInfo(
|
|
|
|
FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
|
2011-09-23 04:07:09 +08:00
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-30 06:39:22 +08:00
|
|
|
void TemplateDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplateSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-30 06:39:22 +08:00
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateSpecializationDecl::
|
2010-05-06 08:28:52 +08:00
|
|
|
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2016-07-04 05:17:51 +08:00
|
|
|
ArrayRef<TemplateArgument> Args,
|
2009-07-30 07:36:44 +08:00
|
|
|
ClassTemplateSpecializationDecl *PrevDecl)
|
2017-11-30 06:39:22 +08:00
|
|
|
: CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
|
|
|
|
SpecializedTemplate->getIdentifier(), PrevDecl),
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
SpecializedTemplate(SpecializedTemplate),
|
2016-07-04 05:17:51 +08:00
|
|
|
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
|
2009-05-12 07:53:27 +08:00
|
|
|
SpecializationKind(TSK_Undeclared) {
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
|
|
|
|
Kind DK)
|
|
|
|
: CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(),
|
|
|
|
SourceLocation(), nullptr, nullptr),
|
2017-11-30 06:39:22 +08:00
|
|
|
SpecializationKind(TSK_Undeclared) {}
|
2010-06-23 21:48:23 +08:00
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateSpecializationDecl *
|
2010-05-06 08:28:52 +08:00
|
|
|
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2016-07-04 05:17:51 +08:00
|
|
|
ArrayRef<TemplateArgument> Args,
|
2009-02-18 07:15:12 +08:00
|
|
|
ClassTemplateSpecializationDecl *PrevDecl) {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *Result =
|
2013-11-22 17:01:48 +08:00
|
|
|
new (Context, DC) ClassTemplateSpecializationDecl(
|
|
|
|
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
|
2016-07-04 05:17:51 +08:00
|
|
|
SpecializedTemplate, Args, PrevDecl);
|
2018-08-02 04:48:16 +08:00
|
|
|
Result->setMayHaveOutOfDateDef(false);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
|
2009-02-18 07:15:12 +08:00
|
|
|
Context.getTypeDeclType(Result, PrevDecl);
|
|
|
|
return Result;
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
}
|
2009-05-31 17:31:02 +08:00
|
|
|
|
2010-06-23 21:48:23 +08:00
|
|
|
ClassTemplateSpecializationDecl *
|
2013-11-22 17:01:48 +08:00
|
|
|
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
|
2012-01-06 05:55:30 +08:00
|
|
|
unsigned ID) {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *Result =
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
|
2018-08-02 04:48:16 +08:00
|
|
|
Result->setMayHaveOutOfDateDef(false);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
return Result;
|
2010-06-23 21:48:23 +08:00
|
|
|
}
|
|
|
|
|
2013-02-22 23:46:01 +08:00
|
|
|
void ClassTemplateSpecializationDecl::getNameForDiagnostic(
|
|
|
|
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
|
|
|
|
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
|
2011-02-20 02:51:44 +08:00
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
|
2016-12-24 12:09:05 +08:00
|
|
|
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
|
|
|
|
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
|
2016-12-24 12:09:05 +08:00
|
|
|
} else {
|
|
|
|
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
|
2016-12-24 12:09:05 +08:00
|
|
|
}
|
2011-02-20 02:51:44 +08:00
|
|
|
}
|
|
|
|
|
2009-08-03 07:24:31 +08:00
|
|
|
ClassTemplateDecl *
|
2009-09-09 23:08:12 +08:00
|
|
|
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *PartialSpec =
|
|
|
|
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
2009-08-03 07:24:31 +08:00
|
|
|
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
|
|
|
|
return SpecializedTemplate.get<ClassTemplateDecl*>();
|
|
|
|
}
|
|
|
|
|
2011-03-04 22:20:30 +08:00
|
|
|
SourceRange
|
|
|
|
ClassTemplateSpecializationDecl::getSourceRange() const {
|
2011-10-04 04:34:03 +08:00
|
|
|
if (ExplicitInfo) {
|
2012-10-16 05:06:42 +08:00
|
|
|
SourceLocation Begin = getTemplateKeywordLoc();
|
|
|
|
if (Begin.isValid()) {
|
|
|
|
// Here we have an explicit (partial) specialization or instantiation.
|
|
|
|
assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
|
|
|
|
getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
|
|
|
|
getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
|
|
|
|
if (getExternLoc().isValid())
|
|
|
|
Begin = getExternLoc();
|
2016-07-16 02:11:33 +08:00
|
|
|
SourceLocation End = getBraceRange().getEnd();
|
2012-10-16 05:06:42 +08:00
|
|
|
if (End.isInvalid())
|
|
|
|
End = getTypeAsWritten()->getTypeLoc().getEndLoc();
|
|
|
|
return SourceRange(Begin, End);
|
|
|
|
}
|
|
|
|
// An implicit instantiation of a class template partial specialization
|
|
|
|
// uses ExplicitInfo to record the TypeAsWritten, but the source
|
|
|
|
// locations should be retrieved from the instantiation pattern.
|
2017-11-30 06:39:22 +08:00
|
|
|
using CTPSDecl = ClassTemplatePartialSpecializationDecl;
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this));
|
2012-10-16 05:06:42 +08:00
|
|
|
CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
|
2014-05-12 13:36:57 +08:00
|
|
|
assert(inst_from != nullptr);
|
2012-10-16 05:06:42 +08:00
|
|
|
return inst_from->getSourceRange();
|
2011-10-04 04:34:03 +08:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// No explicit info available.
|
|
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
|
|
inst_from = getInstantiatedFrom();
|
|
|
|
if (inst_from.isNull())
|
|
|
|
return getSpecializedTemplate()->getSourceRange();
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>())
|
2011-10-04 04:34:03 +08:00
|
|
|
return ctd->getSourceRange();
|
2018-03-30 04:51:59 +08:00
|
|
|
return inst_from.get<ClassTemplatePartialSpecializationDecl *>()
|
2011-10-04 04:34:03 +08:00
|
|
|
->getSourceRange();
|
|
|
|
}
|
2011-03-04 22:20:30 +08:00
|
|
|
}
|
|
|
|
|
2009-05-31 17:31:02 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplatePartialSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-30 06:39:22 +08:00
|
|
|
void ClassTemplatePartialSpecializationDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2011-03-05 01:52:15 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl::
|
|
|
|
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
|
2011-03-09 22:09:51 +08:00
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc,
|
2011-03-05 01:52:15 +08:00
|
|
|
TemplateParameterList *Params,
|
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2016-07-04 05:17:51 +08:00
|
|
|
ArrayRef<TemplateArgument> Args,
|
2013-08-10 15:24:53 +08:00
|
|
|
const ASTTemplateArgumentListInfo *ArgInfos,
|
2013-08-23 07:27:37 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl)
|
2017-11-30 06:39:22 +08:00
|
|
|
: ClassTemplateSpecializationDecl(Context,
|
|
|
|
ClassTemplatePartialSpecialization,
|
|
|
|
TK, DC, StartLoc, IdLoc,
|
|
|
|
SpecializedTemplate, Args, PrevDecl),
|
|
|
|
TemplateParams(Params), ArgsAsWritten(ArgInfos),
|
|
|
|
InstantiatedFromMember(nullptr, false) {
|
2011-03-05 02:32:38 +08:00
|
|
|
AdoptTemplateParameterList(Params, this);
|
2011-03-05 01:52:15 +08:00
|
|
|
}
|
|
|
|
|
2009-05-31 17:31:02 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
|
|
ClassTemplatePartialSpecializationDecl::
|
2011-03-09 22:09:51 +08:00
|
|
|
Create(ASTContext &Context, TagKind TK,DeclContext *DC,
|
|
|
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
2009-05-31 17:31:02 +08:00
|
|
|
TemplateParameterList *Params,
|
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
2016-07-04 05:17:51 +08:00
|
|
|
ArrayRef<TemplateArgument> Args,
|
2009-11-23 09:53:49 +08:00
|
|
|
const TemplateArgumentListInfo &ArgInfos,
|
2010-03-10 11:28:59 +08:00
|
|
|
QualType CanonInjectedType,
|
2013-08-23 07:27:37 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl) {
|
2013-08-10 15:24:53 +08:00
|
|
|
const ASTTemplateArgumentListInfo *ASTArgInfos =
|
|
|
|
ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
|
2009-10-29 16:12:44 +08:00
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *Result = new (Context, DC)
|
2013-11-22 17:01:48 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc,
|
|
|
|
Params, SpecializedTemplate, Args,
|
2016-07-04 05:17:51 +08:00
|
|
|
ASTArgInfos, PrevDecl);
|
2009-05-31 17:31:02 +08:00
|
|
|
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
2018-08-02 04:48:16 +08:00
|
|
|
Result->setMayHaveOutOfDateDef(false);
|
2010-03-10 11:28:59 +08:00
|
|
|
|
|
|
|
Context.getInjectedClassNameType(Result, CanonInjectedType);
|
2009-05-31 17:31:02 +08:00
|
|
|
return Result;
|
|
|
|
}
|
2009-09-17 06:47:08 +08:00
|
|
|
|
2010-06-23 21:48:23 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl *
|
2012-01-06 05:55:30 +08:00
|
|
|
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
|
2018-08-02 04:48:16 +08:00
|
|
|
Result->setMayHaveOutOfDateDef(false);
|
Ensure that type definitions present in just-loaded modules are
visible.
The basic problem here is that a given translation unit can use
forward declarations to form pointers to a given type, say,
class X;
X *x;
and then import a module that includes a definition of X:
import XDef;
We will then fail when attempting to access a member of X, e.g.,
x->method()
because the AST reader did not know to look for a default of a class
named X within the new module.
This implementation is a bit of a C-centric hack, because the only
definitions that can have this property are enums, structs, unions,
Objective-C classes, and Objective-C protocols, and all of those are
either visible at the top-level or can't be defined later. Hence, we
can use the out-of-date-ness of the name and the identifier-update
mechanism to force the update.
In C++, we will not be so lucky, and will need a more advanced
solution, because the definitions could be in namespaces defined in
two different modules, e.g.,
// module 1
namespace N { struct X; }
// module 2
namespace N { struct X { /* ... */ }; }
One possible implementation here is for C++ to extend the information
associated with each identifier table to include the declaration IDs
of any definitions associated with that name, regardless of
context. We would have to eagerly load those definitions.
llvm-svn: 174794
2013-02-09 09:35:03 +08:00
|
|
|
return Result;
|
2010-06-23 21:48:23 +08:00
|
|
|
}
|
|
|
|
|
2009-09-17 06:47:08 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FriendTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-30 06:39:22 +08:00
|
|
|
void FriendTemplateDecl::anchor() {}
|
2011-12-20 10:48:34 +08:00
|
|
|
|
2016-07-06 12:19:16 +08:00
|
|
|
FriendTemplateDecl *
|
|
|
|
FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
MutableArrayRef<TemplateParameterList *> Params,
|
|
|
|
FriendUnion Friend, SourceLocation FLoc) {
|
|
|
|
return new (Context, DC) FriendTemplateDecl(DC, L, Params, Friend, FLoc);
|
2009-09-17 06:47:08 +08:00
|
|
|
}
|
2010-07-23 00:04:10 +08:00
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) FriendTemplateDecl(EmptyShell());
|
2010-07-23 00:04:10 +08:00
|
|
|
}
|
2011-05-06 05:57:07 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TypeAliasTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
|
|
|
NamedDecl *Decl) {
|
|
|
|
AdoptTemplateParameterList(Params, DC);
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
|
2011-05-06 05:57:07 +08:00
|
|
|
}
|
|
|
|
|
2012-01-06 05:55:30 +08:00
|
|
|
TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
|
2014-05-12 13:36:57 +08:00
|
|
|
DeclarationName(), nullptr, nullptr);
|
2011-05-06 05:57:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
2013-01-24 00:52:57 +08:00
|
|
|
TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *CommonPtr = new (C) Common;
|
2017-02-14 13:37:36 +08:00
|
|
|
C.addDestruction(CommonPtr);
|
2011-05-06 05:57:07 +08:00
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassScopeFunctionSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-30 06:39:22 +08:00
|
|
|
void ClassScopeFunctionSpecializationDecl::anchor() {}
|
2012-01-06 05:55:30 +08:00
|
|
|
|
|
|
|
ClassScopeFunctionSpecializationDecl *
|
|
|
|
ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (C, ID) ClassScopeFunctionSpecializationDecl(
|
2019-05-02 08:49:14 +08:00
|
|
|
nullptr, SourceLocation(), nullptr, nullptr);
|
2012-01-06 05:55:30 +08:00
|
|
|
}
|
2013-08-06 09:03:05 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// VarTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-08-13 10:02:26 +08:00
|
|
|
VarTemplateDecl *VarTemplateDecl::getDefinition() {
|
|
|
|
VarTemplateDecl *CurD = this;
|
|
|
|
while (CurD) {
|
|
|
|
if (CurD->isThisDeclarationADefinition())
|
|
|
|
return CurD;
|
|
|
|
CurD = CurD->getPreviousDecl();
|
|
|
|
}
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2013-08-13 10:02:26 +08:00
|
|
|
}
|
|
|
|
|
2013-08-06 09:03:05 +08:00
|
|
|
VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
2014-01-17 07:39:20 +08:00
|
|
|
VarDecl *Decl) {
|
2019-04-20 07:04:05 +08:00
|
|
|
AdoptTemplateParameterList(Params, DC);
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
|
|
|
|
DeclarationName(), nullptr, nullptr);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void VarTemplateDecl::LoadLazySpecializations() const {
|
2017-12-15 07:30:18 +08:00
|
|
|
loadLazySpecializationsImpl();
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
|
|
|
|
VarTemplateDecl::getSpecializations() const {
|
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->Specializations;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
|
|
|
|
VarTemplateDecl::getPartialSpecializations() {
|
|
|
|
LoadLazySpecializations();
|
|
|
|
return getCommonPtr()->PartialSpecializations;
|
|
|
|
}
|
|
|
|
|
|
|
|
RedeclarableTemplateDecl::CommonBase *
|
|
|
|
VarTemplateDecl::newCommon(ASTContext &C) const {
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *CommonPtr = new (C) Common;
|
2017-02-14 13:37:36 +08:00
|
|
|
C.addDestruction(CommonPtr);
|
2013-08-06 09:03:05 +08:00
|
|
|
return CommonPtr;
|
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplateSpecializationDecl *
|
2014-06-26 12:58:53 +08:00
|
|
|
VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
|
|
|
|
void *&InsertPos) {
|
|
|
|
return findSpecializationImpl(getSpecializations(), Args, InsertPos);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
|
|
|
|
void *InsertPos) {
|
2015-02-24 09:23:23 +08:00
|
|
|
addSpecializationImpl<VarTemplateDecl>(getSpecializations(), D, InsertPos);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
2014-06-26 12:58:53 +08:00
|
|
|
VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
|
|
|
|
void *&InsertPos) {
|
|
|
|
return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void VarTemplateDecl::AddPartialSpecialization(
|
|
|
|
VarTemplatePartialSpecializationDecl *D, void *InsertPos) {
|
|
|
|
if (InsertPos)
|
|
|
|
getPartialSpecializations().InsertNode(D, InsertPos);
|
|
|
|
else {
|
|
|
|
VarTemplatePartialSpecializationDecl *Existing =
|
|
|
|
getPartialSpecializations().GetOrInsertNode(D);
|
|
|
|
(void)Existing;
|
|
|
|
assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ASTMutationListener *L = getASTMutationListener())
|
|
|
|
L->AddedCXXTemplateSpecialization(this, D);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VarTemplateDecl::getPartialSpecializations(
|
|
|
|
SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) {
|
|
|
|
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
|
|
|
|
getPartialSpecializations();
|
|
|
|
PS.clear();
|
2013-08-23 07:27:37 +08:00
|
|
|
PS.reserve(PartialSpecs.size());
|
2016-07-06 12:19:16 +08:00
|
|
|
for (VarTemplatePartialSpecializationDecl &P : PartialSpecs)
|
|
|
|
PS.push_back(P.getMostRecentDecl());
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
|
|
|
VarTemplateDecl::findPartialSpecInstantiatedFromMember(
|
|
|
|
VarTemplatePartialSpecializationDecl *D) {
|
|
|
|
Decl *DCanon = D->getCanonicalDecl();
|
2016-07-06 12:19:16 +08:00
|
|
|
for (VarTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
|
|
|
|
if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
|
|
|
|
return P.getMostRecentDecl();
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
2014-05-12 13:36:57 +08:00
|
|
|
return nullptr;
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// VarTemplateSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-30 06:39:22 +08:00
|
|
|
|
2013-08-06 09:03:05 +08:00
|
|
|
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
2013-08-06 09:03:05 +08:00
|
|
|
SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
|
2016-07-04 05:17:51 +08:00
|
|
|
TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args)
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
: VarDecl(DK, Context, DC, StartLoc, IdLoc,
|
|
|
|
SpecializedTemplate->getIdentifier(), T, TInfo, S),
|
2017-11-30 06:39:22 +08:00
|
|
|
SpecializedTemplate(SpecializedTemplate),
|
2016-07-04 05:17:51 +08:00
|
|
|
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
|
2017-12-02 10:48:42 +08:00
|
|
|
SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
|
2013-08-06 09:03:05 +08:00
|
|
|
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
|
|
|
|
ASTContext &C)
|
|
|
|
: VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
|
2014-05-12 13:36:57 +08:00
|
|
|
QualType(), nullptr, SC_None),
|
2017-12-02 10:48:42 +08:00
|
|
|
SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
|
2013-08-06 09:03:05 +08:00
|
|
|
|
|
|
|
VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
|
|
|
|
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
|
2016-07-04 05:17:51 +08:00
|
|
|
TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) {
|
2013-11-22 17:01:48 +08:00
|
|
|
return new (Context, DC) VarTemplateSpecializationDecl(
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
VarTemplateSpecialization, Context, DC, StartLoc, IdLoc,
|
2016-07-04 05:17:51 +08:00
|
|
|
SpecializedTemplate, T, TInfo, S, Args);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplateSpecializationDecl *
|
|
|
|
VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID)
|
|
|
|
VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void VarTemplateSpecializationDecl::getNameForDiagnostic(
|
|
|
|
raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
|
|
|
|
NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
|
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
|
2016-12-24 12:09:05 +08:00
|
|
|
if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
|
|
|
|
PS ? PS->getTemplateArgsAsWritten() : nullptr) {
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
|
2016-12-24 12:09:05 +08:00
|
|
|
} else {
|
|
|
|
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
|
2017-11-29 00:14:14 +08:00
|
|
|
printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
|
2016-12-24 12:09:05 +08:00
|
|
|
}
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
|
2018-03-30 04:51:59 +08:00
|
|
|
if (const auto *PartialSpec =
|
2013-08-06 09:03:05 +08:00
|
|
|
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
|
|
|
|
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
|
|
|
|
return SpecializedTemplate.get<VarTemplateDecl *>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VarTemplateSpecializationDecl::setTemplateArgsInfo(
|
|
|
|
const TemplateArgumentListInfo &ArgsInfo) {
|
|
|
|
TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc());
|
|
|
|
TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc());
|
2016-07-06 12:19:16 +08:00
|
|
|
for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments())
|
|
|
|
TemplateArgsInfo.addArgument(Loc);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// VarTemplatePartialSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-30 06:39:22 +08:00
|
|
|
|
2013-08-06 09:03:05 +08:00
|
|
|
void VarTemplatePartialSpecializationDecl::anchor() {}
|
|
|
|
|
|
|
|
VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
|
|
|
|
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, TemplateParameterList *Params,
|
|
|
|
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
2016-07-04 05:17:51 +08:00
|
|
|
StorageClass S, ArrayRef<TemplateArgument> Args,
|
2013-08-23 07:27:37 +08:00
|
|
|
const ASTTemplateArgumentListInfo *ArgInfos)
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
: VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
|
2013-08-06 09:03:05 +08:00
|
|
|
DC, StartLoc, IdLoc, SpecializedTemplate, T,
|
2016-07-04 05:17:51 +08:00
|
|
|
TInfo, S, Args),
|
2013-08-06 09:03:05 +08:00
|
|
|
TemplateParams(Params), ArgsAsWritten(ArgInfos),
|
2014-05-12 13:36:57 +08:00
|
|
|
InstantiatedFromMember(nullptr, false) {
|
2013-08-06 09:03:05 +08:00
|
|
|
// TODO: The template parameters should be in DC by now. Verify.
|
|
|
|
// AdoptTemplateParameterList(Params, DC);
|
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
|
|
|
VarTemplatePartialSpecializationDecl::Create(
|
|
|
|
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
|
|
|
SourceLocation IdLoc, TemplateParameterList *Params,
|
|
|
|
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
2016-07-04 05:17:51 +08:00
|
|
|
StorageClass S, ArrayRef<TemplateArgument> Args,
|
2013-08-23 07:27:37 +08:00
|
|
|
const TemplateArgumentListInfo &ArgInfos) {
|
2013-08-10 15:24:53 +08:00
|
|
|
const ASTTemplateArgumentListInfo *ASTArgInfos
|
|
|
|
= ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
|
2013-08-06 09:03:05 +08:00
|
|
|
|
2018-03-30 04:51:59 +08:00
|
|
|
auto *Result =
|
2013-11-22 17:01:48 +08:00
|
|
|
new (Context, DC) VarTemplatePartialSpecializationDecl(
|
2013-08-06 09:03:05 +08:00
|
|
|
Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
|
2016-07-04 05:17:51 +08:00
|
|
|
S, Args, ASTArgInfos);
|
2013-08-06 09:03:05 +08:00
|
|
|
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
|
|
|
VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
|
|
unsigned ID) {
|
If a declaration is loaded, and then a module import adds a redeclaration, then
ensure that querying the first declaration for its most recent declaration
checks for redeclarations from the imported module.
This works as follows:
* The 'most recent' pointer on a canonical declaration grows a pointer to the
external AST source and a generation number (space- and time-optimized for
the case where there is no external source).
* Each time the 'most recent' pointer is queried, if it has an external source,
we check whether it's up to date, and update it if not.
* The ancillary data stored on the canonical declaration is allocated lazily
to avoid filling it in for declarations that end up being non-canonical.
We'll still perform a redundant (ASTContext) allocation if someone asks for
the most recent declaration from a decl before setPreviousDecl is called,
but such cases are probably all bugs, and are now easy to find.
Some finessing is still in order here -- in particular, we use a very general
mechanism for handling the DefinitionData pointer on CXXRecordData, and a more
targeted approach would be more compact.
Also, the MayHaveOutOfDateDef mechanism should now be expunged, since it was
addressing only a corner of the full problem space here. That's not covered
by this patch.
Early performance benchmarks show that this makes no measurable difference to
Clang performance without modules enabled (and fixes a major correctness issue
with modules enabled). I'll revert if a full performance comparison shows any
problems.
llvm-svn: 209046
2014-05-17 07:01:30 +08:00
|
|
|
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
|
2013-08-06 09:03:05 +08:00
|
|
|
}
|
2015-11-04 11:40:30 +08:00
|
|
|
|
|
|
|
static TemplateParameterList *
|
|
|
|
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
|
|
|
|
// typename T
|
|
|
|
auto *T = TemplateTypeParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0,
|
|
|
|
/*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
|
|
|
|
T->setImplicit(true);
|
|
|
|
|
|
|
|
// T ...Ints
|
|
|
|
TypeSourceInfo *TI =
|
|
|
|
C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0));
|
|
|
|
auto *N = NonTypeTemplateParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
|
|
|
|
/*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI);
|
|
|
|
N->setImplicit(true);
|
|
|
|
|
|
|
|
// <typename T, T ...Ints>
|
|
|
|
NamedDecl *P[2] = {T, N};
|
|
|
|
auto *TPL = TemplateParameterList::Create(
|
2016-07-31 06:33:34 +08:00
|
|
|
C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr);
|
2015-11-04 11:40:30 +08:00
|
|
|
|
|
|
|
// template <typename T, ...Ints> class IntSeq
|
|
|
|
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
|
|
|
|
/*ParameterPack=*/false, /*Id=*/nullptr, TPL);
|
|
|
|
TemplateTemplateParm->setImplicit(true);
|
|
|
|
|
|
|
|
// typename T
|
|
|
|
auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
|
|
|
|
/*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
|
|
|
|
TemplateTypeParm->setImplicit(true);
|
|
|
|
|
|
|
|
// T N
|
|
|
|
TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(
|
|
|
|
QualType(TemplateTypeParm->getTypeForDecl(), 0));
|
|
|
|
auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2,
|
|
|
|
/*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
|
|
|
|
NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm,
|
|
|
|
NonTypeTemplateParm};
|
|
|
|
|
|
|
|
// template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
|
|
|
|
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
|
2016-07-31 06:33:34 +08:00
|
|
|
Params, SourceLocation(), nullptr);
|
2015-11-04 11:40:30 +08:00
|
|
|
}
|
|
|
|
|
2016-07-01 09:24:09 +08:00
|
|
|
static TemplateParameterList *
|
|
|
|
createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
|
|
|
|
// std::size_t Index
|
|
|
|
TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
|
|
|
|
auto *Index = NonTypeTemplateParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/0,
|
|
|
|
/*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
|
|
|
|
|
|
|
|
// typename ...T
|
|
|
|
auto *Ts = TemplateTypeParmDecl::Create(
|
|
|
|
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
|
|
|
|
/*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true);
|
|
|
|
Ts->setImplicit(true);
|
|
|
|
|
|
|
|
// template <std::size_t Index, typename ...T>
|
|
|
|
NamedDecl *Params[] = {Index, Ts};
|
|
|
|
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
|
|
|
|
llvm::makeArrayRef(Params),
|
2016-07-31 06:33:34 +08:00
|
|
|
SourceLocation(), nullptr);
|
2016-07-01 09:24:09 +08:00
|
|
|
}
|
|
|
|
|
2015-11-04 11:40:30 +08:00
|
|
|
static TemplateParameterList *createBuiltinTemplateParameterList(
|
|
|
|
const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
|
|
|
|
switch (BTK) {
|
|
|
|
case BTK__make_integer_seq:
|
|
|
|
return createMakeIntegerSeqParameterList(C, DC);
|
2016-07-01 09:24:09 +08:00
|
|
|
case BTK__type_pack_element:
|
|
|
|
return createTypePackElementParameterList(C, DC);
|
2015-11-04 11:40:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("unhandled BuiltinTemplateKind!");
|
|
|
|
}
|
|
|
|
|
|
|
|
void BuiltinTemplateDecl::anchor() {}
|
|
|
|
|
|
|
|
BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
|
|
|
|
DeclarationName Name,
|
|
|
|
BuiltinTemplateKind BTK)
|
|
|
|
: TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
|
|
|
|
createBuiltinTemplateParameterList(C, DC, BTK)),
|
|
|
|
BTK(BTK) {}
|