2009-03-18 05:15:40 +08:00
|
|
|
//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//===----------------------------------------------------------------------===/
|
|
|
|
//
|
|
|
|
// This file implements C++ template instantiation for declarations.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===/
|
2010-08-26 06:03:47 +08:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2010-08-13 04:07:10 +08:00
|
|
|
#include "clang/Sema/Lookup.h"
|
2010-08-27 07:41:50 +08:00
|
|
|
#include "clang/Sema/PrettyDeclStackTrace.h"
|
2010-08-24 15:21:54 +08:00
|
|
|
#include "clang/Sema/Template.h"
|
2009-05-27 04:50:29 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2009-03-18 05:15:40 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
|
|
|
#include "clang/AST/DeclVisitor.h"
|
2010-03-24 13:22:00 +08:00
|
|
|
#include "clang/AST/DependentDiagnostic.h"
|
2009-03-18 05:15:40 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-12-13 02:16:41 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2010-03-11 17:03:00 +08:00
|
|
|
#include "clang/AST/TypeLoc.h"
|
2009-08-27 05:14:46 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2009-03-18 05:15:40 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2010-03-15 18:12:16 +08:00
|
|
|
bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
|
|
|
|
DeclaratorDecl *NewDecl) {
|
2011-02-25 10:25:35 +08:00
|
|
|
if (!OldDecl->getQualifierLoc())
|
|
|
|
return false;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NestedNameSpecifierLoc NewQualifierLoc
|
2011-10-08 19:31:46 +08:00
|
|
|
= SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
|
2011-02-25 10:25:35 +08:00
|
|
|
TemplateArgs);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
if (!NewQualifierLoc)
|
2010-03-15 18:12:16 +08:00
|
|
|
return true;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NewDecl->setQualifierInfo(NewQualifierLoc);
|
2010-03-15 18:12:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
|
|
|
|
TagDecl *NewDecl) {
|
2011-02-25 10:25:35 +08:00
|
|
|
if (!OldDecl->getQualifierLoc())
|
|
|
|
return false;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NestedNameSpecifierLoc NewQualifierLoc
|
2011-10-08 19:31:46 +08:00
|
|
|
= SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
|
2011-02-25 10:25:35 +08:00
|
|
|
TemplateArgs);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
if (!NewQualifierLoc)
|
2010-03-15 18:12:16 +08:00
|
|
|
return true;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NewDecl->setQualifierInfo(NewQualifierLoc);
|
2010-03-15 18:12:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-01-21 06:37:06 +08:00
|
|
|
// Include attribute instantiation code.
|
|
|
|
#include "clang/Sema/AttrTemplateInstantiate.inc"
|
|
|
|
|
2010-08-01 10:01:53 +08:00
|
|
|
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
2012-01-21 06:50:54 +08:00
|
|
|
const Decl *Tmpl, Decl *New,
|
|
|
|
LateInstantiatedAttrVec *LateAttrs,
|
|
|
|
LocalInstantiationScope *OuterMostScope) {
|
2010-08-19 07:23:40 +08:00
|
|
|
for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
|
|
|
|
i != e; ++i) {
|
|
|
|
const Attr *TmplAttr = *i;
|
2012-01-21 06:50:54 +08:00
|
|
|
|
2010-06-25 11:22:07 +08:00
|
|
|
// FIXME: This should be generalized to more than just the AlignedAttr.
|
|
|
|
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
|
2010-08-19 07:23:40 +08:00
|
|
|
if (Aligned->isAlignmentDependent()) {
|
|
|
|
if (Aligned->isAlignmentExpr()) {
|
2011-12-20 10:08:33 +08:00
|
|
|
// The alignment expression is a constant expression.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(*this,
|
|
|
|
Sema::ConstantEvaluated);
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
|
2010-11-20 09:29:55 +08:00
|
|
|
TemplateArgs);
|
2010-08-19 07:23:40 +08:00
|
|
|
if (!Result.isInvalid())
|
2012-06-20 06:09:27 +08:00
|
|
|
AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(),
|
|
|
|
Aligned->getIsMSDeclSpec());
|
2011-12-20 10:08:33 +08:00
|
|
|
} else {
|
2010-08-19 07:23:40 +08:00
|
|
|
TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
|
2010-11-20 09:29:55 +08:00
|
|
|
TemplateArgs,
|
2011-10-08 19:31:46 +08:00
|
|
|
Aligned->getLocation(),
|
2010-11-20 09:29:55 +08:00
|
|
|
DeclarationName());
|
2010-08-19 07:23:40 +08:00
|
|
|
if (Result)
|
2012-06-20 06:09:27 +08:00
|
|
|
AddAlignedAttr(Aligned->getLocation(), New, Result,
|
|
|
|
Aligned->getIsMSDeclSpec());
|
2010-08-19 07:23:40 +08:00
|
|
|
}
|
2010-06-25 11:22:07 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-21 06:50:54 +08:00
|
|
|
if (TmplAttr->isLateParsed() && LateAttrs) {
|
|
|
|
// Late parsed attributes must be instantiated and attached after the
|
|
|
|
// enclosing class has been instantiated. See Sema::InstantiateClass.
|
|
|
|
LocalInstantiationScope *Saved = 0;
|
|
|
|
if (CurrentInstantiationScope)
|
|
|
|
Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
|
|
|
|
LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
|
|
|
|
} else {
|
2012-02-06 19:13:08 +08:00
|
|
|
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
|
|
|
|
*this, TemplateArgs);
|
2012-05-15 22:09:55 +08:00
|
|
|
if (NewAttr)
|
|
|
|
New->addAttr(NewAttr);
|
2012-01-21 06:50:54 +08:00
|
|
|
}
|
2009-11-07 14:07:58 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-25 23:45:12 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Translation units cannot be instantiated");
|
2009-03-25 23:45:12 +08:00
|
|
|
}
|
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {
|
|
|
|
LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
|
|
|
D->getIdentifier());
|
|
|
|
Owner->addDecl(Inst);
|
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2009-03-25 23:45:12 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) {
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Namespaces cannot be instantiated");
|
2009-03-25 23:45:12 +08:00
|
|
|
}
|
|
|
|
|
2010-02-16 14:53:13 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
|
|
|
|
NamespaceAliasDecl *Inst
|
|
|
|
= NamespaceAliasDecl::Create(SemaRef.Context, Owner,
|
|
|
|
D->getNamespaceLoc(),
|
|
|
|
D->getAliasLoc(),
|
2011-02-26 01:08:07 +08:00
|
|
|
D->getIdentifier(),
|
|
|
|
D->getQualifierLoc(),
|
2010-02-16 14:53:13 +08:00
|
|
|
D->getTargetNameLoc(),
|
|
|
|
D->getNamespace());
|
|
|
|
Owner->addDecl(Inst);
|
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2011-05-06 05:57:07 +08:00
|
|
|
Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
|
|
|
|
bool IsTypeAlias) {
|
2009-03-18 05:15:40 +08:00
|
|
|
bool Invalid = false;
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *DI = D->getTypeSourceInfo();
|
2011-07-01 09:22:09 +08:00
|
|
|
if (DI->getType()->isInstantiationDependentType() ||
|
2010-05-25 01:22:01 +08:00
|
|
|
DI->getType()->isVariablyModifiedType()) {
|
2009-10-24 16:00:42 +08:00
|
|
|
DI = SemaRef.SubstType(DI, TemplateArgs,
|
|
|
|
D->getLocation(), D->getDeclName());
|
|
|
|
if (!DI) {
|
2009-03-18 05:15:40 +08:00
|
|
|
Invalid = true;
|
2009-12-07 10:54:59 +08:00
|
|
|
DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy);
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
2010-05-08 07:12:07 +08:00
|
|
|
} else {
|
|
|
|
SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-18 05:15:40 +08:00
|
|
|
// Create the new typedef
|
2011-04-15 22:24:37 +08:00
|
|
|
TypedefNameDecl *Typedef;
|
|
|
|
if (IsTypeAlias)
|
|
|
|
Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
|
|
|
|
D->getLocation(), D->getIdentifier(), DI);
|
|
|
|
else
|
|
|
|
Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
|
|
|
|
D->getLocation(), D->getIdentifier(), DI);
|
2009-03-18 05:15:40 +08:00
|
|
|
if (Invalid)
|
|
|
|
Typedef->setInvalidDecl();
|
|
|
|
|
2011-02-01 16:20:08 +08:00
|
|
|
// If the old typedef was the name for linkage purposes of an anonymous
|
|
|
|
// tag decl, re-establish that relationship for the new typedef.
|
|
|
|
if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) {
|
|
|
|
TagDecl *oldTag = oldTagType->getDecl();
|
2011-04-15 22:24:37 +08:00
|
|
|
if (oldTag->getTypedefNameForAnonDecl() == D) {
|
2011-02-01 16:20:08 +08:00
|
|
|
TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl();
|
2011-04-15 22:24:37 +08:00
|
|
|
assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl());
|
|
|
|
newTag->setTypedefNameForAnonDecl(Typedef);
|
2011-02-01 16:20:08 +08:00
|
|
|
}
|
2010-04-24 00:25:07 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2012-01-15 00:38:05 +08:00
|
|
|
if (TypedefNameDecl *Prev = D->getPreviousDecl()) {
|
2010-03-01 23:56:25 +08:00
|
|
|
NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,
|
|
|
|
TemplateArgs);
|
2011-03-05 03:46:35 +08:00
|
|
|
if (!InstPrev)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-12-27 06:42:47 +08:00
|
|
|
TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev);
|
|
|
|
|
|
|
|
// If the typedef types are not identical, reject them.
|
|
|
|
SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef);
|
|
|
|
|
|
|
|
Typedef->setPreviousDeclaration(InstPrevTypedef);
|
2009-12-30 08:31:22 +08:00
|
|
|
}
|
|
|
|
|
2010-08-01 10:01:53 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
|
2010-04-24 00:25:07 +08:00
|
|
|
|
2010-01-21 05:53:11 +08:00
|
|
|
Typedef->setAccess(D->getAccess());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-18 05:15:40 +08:00
|
|
|
return Typedef;
|
|
|
|
}
|
|
|
|
|
2011-04-15 22:24:37 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
|
2011-05-06 05:57:07 +08:00
|
|
|
Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false);
|
|
|
|
Owner->addDecl(Typedef);
|
|
|
|
return Typedef;
|
2011-04-15 22:24:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) {
|
2011-05-06 05:57:07 +08:00
|
|
|
Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true);
|
|
|
|
Owner->addDecl(Typedef);
|
|
|
|
return Typedef;
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
|
|
|
|
// Create a local instantiation scope for this type alias template, which
|
|
|
|
// will contain the instantiations of the template parameters.
|
|
|
|
LocalInstantiationScope Scope(SemaRef);
|
|
|
|
|
|
|
|
TemplateParameterList *TempParams = D->getTemplateParameters();
|
|
|
|
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
|
|
|
|
if (!InstParams)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
TypeAliasDecl *Pattern = D->getTemplatedDecl();
|
|
|
|
|
|
|
|
TypeAliasTemplateDecl *PrevAliasTemplate = 0;
|
2012-01-15 00:38:05 +08:00
|
|
|
if (Pattern->getPreviousDecl()) {
|
2011-05-06 05:57:07 +08:00
|
|
|
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
|
|
|
|
if (Found.first != Found.second) {
|
|
|
|
PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>(
|
|
|
|
InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true));
|
|
|
|
if (!AliasInst)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
TypeAliasTemplateDecl *Inst
|
|
|
|
= TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
|
|
|
D->getDeclName(), InstParams, AliasInst);
|
|
|
|
if (PrevAliasTemplate)
|
|
|
|
Inst->setPreviousDeclaration(PrevAliasTemplate);
|
|
|
|
|
|
|
|
Inst->setAccess(D->getAccess());
|
|
|
|
|
|
|
|
if (!PrevAliasTemplate)
|
|
|
|
Inst->setInstantiatedFromMemberTemplate(D);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-05-06 05:57:07 +08:00
|
|
|
Owner->addDecl(Inst);
|
|
|
|
|
|
|
|
return Inst;
|
2011-04-15 22:24:37 +08:00
|
|
|
}
|
|
|
|
|
2009-03-26 07:32:15 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
2010-05-21 08:31:19 +08:00
|
|
|
// If this is the variable for an anonymous struct or union,
|
|
|
|
// instantiate the anonymous struct/union type first.
|
|
|
|
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
|
|
|
|
if (RecordTy->getDecl()->isAnonymousStructOrUnion())
|
|
|
|
if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
|
|
|
|
return 0;
|
|
|
|
|
2009-08-26 06:02:44 +08:00
|
|
|
// Do substitution on the type of the declaration
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
|
2009-10-21 10:39:02 +08:00
|
|
|
TemplateArgs,
|
|
|
|
D->getTypeSpecStartLoc(),
|
|
|
|
D->getDeclName());
|
|
|
|
if (!DI)
|
2009-03-26 07:32:15 +08:00
|
|
|
return 0;
|
|
|
|
|
2010-09-12 15:37:24 +08:00
|
|
|
if (DI->getType()->isFunctionType()) {
|
|
|
|
SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function)
|
|
|
|
<< D->isStaticDataMember() << DI->getType();
|
|
|
|
return 0;
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-05-15 08:01:03 +08:00
|
|
|
// Build the instantiated declaration
|
2009-03-26 07:32:15 +08:00
|
|
|
VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,
|
2011-03-08 16:55:46 +08:00
|
|
|
D->getInnerLocStart(),
|
2009-03-26 07:32:15 +08:00
|
|
|
D->getLocation(), D->getIdentifier(),
|
2009-10-21 10:39:02 +08:00
|
|
|
DI->getType(), DI,
|
2010-04-20 06:54:31 +08:00
|
|
|
D->getStorageClass(),
|
|
|
|
D->getStorageClassAsWritten());
|
2009-03-26 07:32:15 +08:00
|
|
|
Var->setThreadSpecified(D->isThreadSpecified());
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
Var->setInitStyle(D->getInitStyle());
|
2011-04-15 06:09:26 +08:00
|
|
|
Var->setCXXForRangeDecl(D->isCXXForRangeDecl());
|
2012-01-20 06:46:17 +08:00
|
|
|
Var->setConstexpr(D->isConstexpr());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-15 18:12:16 +08:00
|
|
|
// Substitute the nested name specifier, if any.
|
|
|
|
if (SubstQualifier(D, Var))
|
|
|
|
return 0;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// If we are instantiating a static data member defined
|
2009-07-25 04:34:43 +08:00
|
|
|
// out-of-line, the instantiation will have the same lexical
|
|
|
|
// context (which will be a namespace scope) as the template.
|
|
|
|
if (D->isOutOfLine())
|
|
|
|
Var->setLexicalDeclContext(D->getLexicalDeclContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-21 05:53:11 +08:00
|
|
|
Var->setAccess(D->getAccess());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-04-20 03:51:10 +08:00
|
|
|
if (!D->isStaticDataMember()) {
|
2010-06-18 07:14:26 +08:00
|
|
|
Var->setUsed(D->isUsed(false));
|
2011-04-20 03:51:10 +08:00
|
|
|
Var->setReferenced(D->isReferenced());
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-05-16 15:39:55 +08:00
|
|
|
// FIXME: In theory, we could have a previous declaration for variables that
|
|
|
|
// are not static data members.
|
2009-11-19 06:49:29 +08:00
|
|
|
// FIXME: having to fake up a LookupResult is dumb.
|
|
|
|
LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
|
2010-03-02 03:11:54 +08:00
|
|
|
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
2010-02-09 15:26:29 +08:00
|
|
|
if (D->isStaticDataMember())
|
|
|
|
SemaRef.LookupQualifiedName(Previous, Owner, false);
|
2011-12-10 09:22:52 +08:00
|
|
|
|
|
|
|
// In ARC, infer 'retaining' for variables of retainable type.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
|
2011-12-10 09:22:52 +08:00
|
|
|
SemaRef.inferObjCARCLifetime(Var))
|
|
|
|
Var->setInvalidDecl();
|
|
|
|
|
2011-10-11 08:28:45 +08:00
|
|
|
SemaRef.CheckVariableDeclaration(Var, Previous);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
if (D->isOutOfLine()) {
|
2011-12-21 08:25:33 +08:00
|
|
|
D->getLexicalDeclContext()->addDecl(Var);
|
2009-07-25 04:34:43 +08:00
|
|
|
Owner->makeDeclVisibleInContext(Var);
|
|
|
|
} else {
|
|
|
|
Owner->addDecl(Var);
|
2010-05-04 04:22:41 +08:00
|
|
|
if (Owner->isFunctionOrMethod())
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
|
2009-07-25 04:34:43 +08:00
|
|
|
}
|
2012-02-17 01:30:51 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-08 15:24:58 +08:00
|
|
|
// Link instantiations of static data members back to the template from
|
|
|
|
// which they were instantiated.
|
|
|
|
if (Var->isStaticDataMember())
|
2011-10-08 19:31:46 +08:00
|
|
|
SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D,
|
2009-11-02 04:32:48 +08:00
|
|
|
TSK_ImplicitInstantiation);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-02-09 15:26:29 +08:00
|
|
|
if (Var->getAnyInitializer()) {
|
|
|
|
// We already have an initializer in the class.
|
|
|
|
} else if (D->getInit()) {
|
2009-12-04 01:10:37 +08:00
|
|
|
if (Var->isStaticDataMember() && !D->isOutOfLine())
|
2012-07-23 07:45:10 +08:00
|
|
|
SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated, D);
|
2009-12-04 01:10:37 +08:00
|
|
|
else
|
2012-07-23 07:45:10 +08:00
|
|
|
SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, D);
|
2009-12-04 01:10:37 +08:00
|
|
|
|
2010-03-02 15:38:39 +08:00
|
|
|
// Instantiate the initializer.
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs,
|
|
|
|
D->getInitStyle() == VarDecl::CallInit);
|
|
|
|
if (!Init.isInvalid()) {
|
2011-02-20 11:19:35 +08:00
|
|
|
bool TypeMayContainAuto = true;
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
if (Init.get()) {
|
|
|
|
bool DirectInit = D->isDirectInit();
|
|
|
|
SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit,
|
|
|
|
TypeMayContainAuto);
|
|
|
|
} else
|
2012-01-06 06:34:08 +08:00
|
|
|
SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto);
|
2009-12-15 03:27:10 +08:00
|
|
|
} else {
|
2010-03-02 15:38:39 +08:00
|
|
|
// FIXME: Not too happy about invalidating the declaration
|
|
|
|
// because of a bogus initializer.
|
|
|
|
Var->setInvalidDecl();
|
2009-12-15 03:27:10 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-12-04 01:10:37 +08:00
|
|
|
SemaRef.PopExpressionEvaluationContext();
|
2011-04-15 06:09:26 +08:00
|
|
|
} else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) &&
|
|
|
|
!Var->isCXXForRangeDecl())
|
2010-08-21 17:40:31 +08:00
|
|
|
SemaRef.ActOnUninitializedDecl(Var, false);
|
2009-03-26 07:32:15 +08:00
|
|
|
|
2011-06-22 07:42:09 +08:00
|
|
|
// Diagnose unused local variables with dependent types, where the diagnostic
|
|
|
|
// will have been deferred.
|
|
|
|
if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed() &&
|
|
|
|
D->getType()->isDependentType())
|
2010-05-09 07:05:03 +08:00
|
|
|
SemaRef.DiagnoseUnusedDecl(Var);
|
2010-08-15 09:15:20 +08:00
|
|
|
|
2009-03-26 07:32:15 +08:00
|
|
|
return Var;
|
|
|
|
}
|
|
|
|
|
2010-06-05 13:09:32 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) {
|
|
|
|
AccessSpecDecl* AD
|
|
|
|
= AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner,
|
|
|
|
D->getAccessSpecifierLoc(), D->getColonLoc());
|
|
|
|
Owner->addHiddenDecl(AD);
|
|
|
|
return AD;
|
|
|
|
}
|
|
|
|
|
2009-03-18 05:15:40 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
|
|
|
|
bool Invalid = false;
|
2009-12-07 10:54:59 +08:00
|
|
|
TypeSourceInfo *DI = D->getTypeSourceInfo();
|
2011-07-01 09:22:09 +08:00
|
|
|
if (DI->getType()->isInstantiationDependentType() ||
|
2010-05-25 01:22:01 +08:00
|
|
|
DI->getType()->isVariablyModifiedType()) {
|
2009-10-23 07:33:21 +08:00
|
|
|
DI = SemaRef.SubstType(DI, TemplateArgs,
|
|
|
|
D->getLocation(), D->getDeclName());
|
|
|
|
if (!DI) {
|
2009-12-07 10:54:59 +08:00
|
|
|
DI = D->getTypeSourceInfo();
|
2009-10-23 07:33:21 +08:00
|
|
|
Invalid = true;
|
|
|
|
} else if (DI->getType()->isFunctionType()) {
|
2009-03-18 05:15:40 +08:00
|
|
|
// C++ [temp.arg.type]p3:
|
|
|
|
// If a declaration acquires a function type through a type
|
|
|
|
// dependent on a template-parameter and this causes a
|
|
|
|
// declaration that does not use the syntactic form of a
|
|
|
|
// function declarator to have function type, the program is
|
|
|
|
// ill-formed.
|
|
|
|
SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function)
|
2009-10-23 07:33:21 +08:00
|
|
|
<< DI->getType();
|
2009-03-18 05:15:40 +08:00
|
|
|
Invalid = true;
|
|
|
|
}
|
2010-05-08 07:12:07 +08:00
|
|
|
} else {
|
|
|
|
SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType());
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Expr *BitWidth = D->getBitWidth();
|
|
|
|
if (Invalid)
|
|
|
|
BitWidth = 0;
|
|
|
|
else if (BitWidth) {
|
2011-12-20 10:08:33 +08:00
|
|
|
// The bit-width expression is a constant expression.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef,
|
|
|
|
Sema::ConstantEvaluated);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult InstantiatedBitWidth
|
2009-08-26 06:02:44 +08:00
|
|
|
= SemaRef.SubstExpr(BitWidth, TemplateArgs);
|
2009-03-18 05:15:40 +08:00
|
|
|
if (InstantiatedBitWidth.isInvalid()) {
|
|
|
|
Invalid = true;
|
|
|
|
BitWidth = 0;
|
|
|
|
} else
|
2009-05-02 03:49:17 +08:00
|
|
|
BitWidth = InstantiatedBitWidth.takeAs<Expr>();
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
|
|
|
|
2009-10-23 07:33:21 +08:00
|
|
|
FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(),
|
|
|
|
DI->getType(), DI,
|
2009-09-09 23:08:12 +08:00
|
|
|
cast<RecordDecl>(Owner),
|
2009-03-18 05:15:40 +08:00
|
|
|
D->getLocation(),
|
|
|
|
D->isMutable(),
|
|
|
|
BitWidth,
|
2012-06-10 11:12:00 +08:00
|
|
|
D->getInClassInitStyle(),
|
2012-05-23 12:22:22 +08:00
|
|
|
D->getInnerLocStart(),
|
2009-03-18 05:15:40 +08:00
|
|
|
D->getAccess(),
|
|
|
|
0);
|
2009-10-15 04:14:33 +08:00
|
|
|
if (!Field) {
|
|
|
|
cast<Decl>(Owner)->setInvalidDecl();
|
2009-09-03 03:17:55 +08:00
|
|
|
return 0;
|
2009-10-15 04:14:33 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-21 06:50:54 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-09-03 03:17:55 +08:00
|
|
|
if (Invalid)
|
|
|
|
Field->setInvalidDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-03 03:17:55 +08:00
|
|
|
if (!Field->getDeclName()) {
|
|
|
|
// Keep track of where this decl came from.
|
|
|
|
SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D);
|
2011-10-08 19:31:46 +08:00
|
|
|
}
|
2010-05-21 08:31:19 +08:00
|
|
|
if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) {
|
|
|
|
if (Parent->isAnonymousStructOrUnion() &&
|
2010-08-31 08:36:30 +08:00
|
|
|
Parent->getRedeclContext()->isFunctionOrMethod())
|
2010-05-21 08:31:19 +08:00
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field);
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-03 03:17:55 +08:00
|
|
|
Field->setImplicit(D->isImplicit());
|
2010-01-21 05:53:11 +08:00
|
|
|
Field->setAccess(D->getAccess());
|
2009-09-03 03:17:55 +08:00
|
|
|
Owner->addDecl(Field);
|
2009-03-18 05:15:40 +08:00
|
|
|
|
|
|
|
return Field;
|
|
|
|
}
|
|
|
|
|
2010-11-21 14:08:52 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
|
|
|
|
NamedDecl **NamedChain =
|
|
|
|
new (SemaRef.Context)NamedDecl*[D->getChainingSize()];
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
for (IndirectFieldDecl::chain_iterator PI =
|
|
|
|
D->chain_begin(), PE = D->chain_end();
|
2011-03-05 03:46:35 +08:00
|
|
|
PI != PE; ++PI) {
|
2011-10-08 19:31:46 +08:00
|
|
|
NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI,
|
2011-03-05 03:46:35 +08:00
|
|
|
TemplateArgs);
|
|
|
|
if (!Next)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-03-05 03:46:35 +08:00
|
|
|
NamedChain[i++] = Next;
|
|
|
|
}
|
2010-11-21 14:08:52 +08:00
|
|
|
|
2010-12-09 18:07:54 +08:00
|
|
|
QualType T = cast<FieldDecl>(NamedChain[i-1])->getType();
|
2010-11-21 14:08:52 +08:00
|
|
|
IndirectFieldDecl* IndirectField
|
|
|
|
= IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
2010-12-09 18:07:54 +08:00
|
|
|
D->getIdentifier(), T,
|
2010-11-21 14:08:52 +08:00
|
|
|
NamedChain, D->getChainingSize());
|
|
|
|
|
|
|
|
|
|
|
|
IndirectField->setImplicit(D->isImplicit());
|
|
|
|
IndirectField->setAccess(D->getAccess());
|
|
|
|
Owner->addDecl(IndirectField);
|
|
|
|
return IndirectField;
|
|
|
|
}
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
|
|
|
|
// Handle friend type expressions by simply substituting template
|
2010-04-08 01:57:12 +08:00
|
|
|
// parameters into the pattern type and checking the result.
|
2010-03-26 02:04:51 +08:00
|
|
|
if (TypeSourceInfo *Ty = D->getFriendType()) {
|
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
|
|
|
TypeSourceInfo *InstTy;
|
|
|
|
// If this is an unsupported friend, don't bother substituting template
|
|
|
|
// arguments into it. The actual type referred to won't be used by any
|
|
|
|
// parts of Clang, and may not be valid for instantiating. Just use the
|
|
|
|
// same info for the instantiated friend.
|
|
|
|
if (D->isUnsupportedFriend()) {
|
|
|
|
InstTy = Ty;
|
|
|
|
} else {
|
|
|
|
InstTy = SemaRef.SubstType(Ty, TemplateArgs,
|
|
|
|
D->getLocation(), DeclarationName());
|
|
|
|
}
|
|
|
|
if (!InstTy)
|
2010-04-08 01:57:12 +08:00
|
|
|
return 0;
|
2009-08-14 10:03:10 +08:00
|
|
|
|
2011-10-30 04:52:52 +08:00
|
|
|
FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(),
|
|
|
|
D->getFriendLoc(), InstTy);
|
2010-04-08 01:57:12 +08:00
|
|
|
if (!FD)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-04-08 01:57:12 +08:00
|
|
|
FD->setAccess(AS_public);
|
2010-10-19 09:40:49 +08:00
|
|
|
FD->setUnsupportedFriend(D->isUnsupportedFriend());
|
2010-04-08 01:57:12 +08:00
|
|
|
Owner->addDecl(FD);
|
|
|
|
return FD;
|
2011-10-08 19:31:46 +08:00
|
|
|
}
|
|
|
|
|
2010-04-08 01:57:12 +08:00
|
|
|
NamedDecl *ND = D->getFriendDecl();
|
|
|
|
assert(ND && "friend decl must be a decl or a type!");
|
2010-03-26 02:04:51 +08:00
|
|
|
|
2010-04-08 17:05:18 +08:00
|
|
|
// All of the Visit implementations for the various potential friend
|
|
|
|
// declarations have to be carefully written to work for friend
|
|
|
|
// objects, with the most important detail being that the target
|
|
|
|
// decl should almost certainly not be placed in Owner.
|
|
|
|
Decl *NewND = Visit(ND);
|
2010-04-08 01:57:12 +08:00
|
|
|
if (!NewND) return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
FriendDecl *FD =
|
2011-10-08 19:31:46 +08:00
|
|
|
FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
2010-04-08 01:57:12 +08:00
|
|
|
cast<NamedDecl>(NewND), D->getFriendLoc());
|
2009-08-29 11:50:18 +08:00
|
|
|
FD->setAccess(AS_public);
|
2010-10-19 09:40:49 +08:00
|
|
|
FD->setUnsupportedFriend(D->isUnsupportedFriend());
|
2009-08-28 15:59:38 +08:00
|
|
|
Owner->addDecl(FD);
|
|
|
|
return FD;
|
2009-08-14 10:03:10 +08:00
|
|
|
}
|
|
|
|
|
2009-03-18 05:15:40 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
|
|
|
Expr *AssertExpr = D->getAssertExpr();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-20 10:08:33 +08:00
|
|
|
// The expression in a static assertion is a constant expression.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef,
|
|
|
|
Sema::ConstantEvaluated);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult InstantiatedAssertExpr
|
2009-08-26 06:02:44 +08:00
|
|
|
= SemaRef.SubstExpr(AssertExpr, TemplateArgs);
|
2009-03-18 05:15:40 +08:00
|
|
|
if (InstantiatedAssertExpr.isInvalid())
|
|
|
|
return 0;
|
|
|
|
|
2012-07-12 06:37:56 +08:00
|
|
|
return SemaRef.BuildStaticAssertDeclaration(D->getLocation(),
|
2010-08-24 07:25:46 +08:00
|
|
|
InstantiatedAssertExpr.get(),
|
2012-07-12 06:37:56 +08:00
|
|
|
D->getMessage(),
|
|
|
|
D->getRParenLoc(),
|
|
|
|
D->isFailed());
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
|
2012-03-26 12:58:10 +08:00
|
|
|
EnumDecl *PrevDecl = 0;
|
|
|
|
if (D->getPreviousDecl()) {
|
|
|
|
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
|
|
|
|
D->getPreviousDecl(),
|
|
|
|
TemplateArgs);
|
|
|
|
if (!Prev) return 0;
|
|
|
|
PrevDecl = cast<EnumDecl>(Prev);
|
|
|
|
}
|
|
|
|
|
2011-03-09 22:09:51 +08:00
|
|
|
EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(),
|
2009-03-18 05:15:40 +08:00
|
|
|
D->getLocation(), D->getIdentifier(),
|
2012-03-26 12:58:10 +08:00
|
|
|
PrevDecl, D->isScoped(),
|
2010-12-04 02:54:17 +08:00
|
|
|
D->isScopedUsingClassTag(), D->isFixed());
|
2010-10-09 07:50:27 +08:00
|
|
|
if (D->isFixed()) {
|
2012-03-15 07:13:10 +08:00
|
|
|
if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) {
|
2010-10-09 07:50:27 +08:00
|
|
|
// If we have type source information for the underlying type, it means it
|
|
|
|
// has been explicitly set by the user. Perform substitution on it before
|
|
|
|
// moving on.
|
|
|
|
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
|
2012-03-15 07:13:10 +08:00
|
|
|
TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc,
|
|
|
|
DeclarationName());
|
|
|
|
if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI))
|
2010-10-09 07:50:27 +08:00
|
|
|
Enum->setIntegerType(SemaRef.Context.IntTy);
|
2012-03-15 07:13:10 +08:00
|
|
|
else
|
|
|
|
Enum->setIntegerTypeSourceInfo(NewTI);
|
|
|
|
} else {
|
2010-10-09 07:50:27 +08:00
|
|
|
assert(!D->getIntegerType()->isDependentType()
|
|
|
|
&& "Dependent type without type source info");
|
|
|
|
Enum->setIntegerType(D->getIntegerType());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-23 07:36:17 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, D, Enum);
|
|
|
|
|
2012-03-15 07:13:10 +08:00
|
|
|
Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation);
|
2009-03-26 06:00:53 +08:00
|
|
|
Enum->setAccess(D->getAccess());
|
2010-03-15 18:12:16 +08:00
|
|
|
if (SubstQualifier(D, Enum)) return 0;
|
2009-06-30 10:36:12 +08:00
|
|
|
Owner->addDecl(Enum);
|
2012-03-15 07:13:10 +08:00
|
|
|
|
2012-03-26 12:08:46 +08:00
|
|
|
EnumDecl *Def = D->getDefinition();
|
|
|
|
if (Def && Def != D) {
|
|
|
|
// If this is an out-of-line definition of an enum member template, check
|
|
|
|
// that the underlying types match in the instantiation of both
|
|
|
|
// declarations.
|
|
|
|
if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) {
|
|
|
|
SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc();
|
|
|
|
QualType DefnUnderlying =
|
|
|
|
SemaRef.SubstType(TI->getType(), TemplateArgs,
|
|
|
|
UnderlyingLoc, DeclarationName());
|
|
|
|
SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(),
|
|
|
|
DefnUnderlying, Enum);
|
|
|
|
}
|
|
|
|
}
|
2009-03-18 05:15:40 +08:00
|
|
|
|
2010-03-02 03:00:07 +08:00
|
|
|
if (D->getDeclContext()->isFunctionOrMethod())
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2012-03-15 07:13:10 +08:00
|
|
|
// C++11 [temp.inst]p1: The implicit instantiation of a class template
|
|
|
|
// specialization causes the implicit instantiation of the declarations, but
|
|
|
|
// not the definitions of scoped member enumerations.
|
|
|
|
// FIXME: There appears to be no wording for what happens for an enum defined
|
2012-03-26 12:58:10 +08:00
|
|
|
// within a block scope, but we treat that much like a member template. Only
|
|
|
|
// instantiate the definition when visiting the definition in that case, since
|
|
|
|
// we will visit all redeclarations.
|
|
|
|
if (!Enum->isScoped() && Def &&
|
|
|
|
(!D->getDeclContext()->isFunctionOrMethod() || D->isCompleteDefinition()))
|
2012-03-26 12:08:46 +08:00
|
|
|
InstantiateEnumDefinition(Enum, Def);
|
2012-03-15 07:13:10 +08:00
|
|
|
|
|
|
|
return Enum;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateDeclInstantiator::InstantiateEnumDefinition(
|
|
|
|
EnumDecl *Enum, EnumDecl *Pattern) {
|
|
|
|
Enum->startDefinition();
|
|
|
|
|
2012-03-23 11:33:32 +08:00
|
|
|
// Update the location to refer to the definition.
|
|
|
|
Enum->setLocation(Pattern->getLocation());
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Decl*, 4> Enumerators;
|
2009-03-18 05:15:40 +08:00
|
|
|
|
|
|
|
EnumConstantDecl *LastEnumConst = 0;
|
2012-03-15 07:13:10 +08:00
|
|
|
for (EnumDecl::enumerator_iterator EC = Pattern->enumerator_begin(),
|
|
|
|
ECEnd = Pattern->enumerator_end();
|
2009-03-18 05:15:40 +08:00
|
|
|
EC != ECEnd; ++EC) {
|
|
|
|
// The specified value for the enumerator.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Value = SemaRef.Owned((Expr *)0);
|
2009-06-23 04:57:11 +08:00
|
|
|
if (Expr *UninstValue = EC->getInitExpr()) {
|
2011-12-20 10:08:33 +08:00
|
|
|
// The enumerator's value expression is a constant expression.
|
2009-09-09 23:08:12 +08:00
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef,
|
2011-12-20 10:08:33 +08:00
|
|
|
Sema::ConstantEvaluated);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-26 06:02:44 +08:00
|
|
|
Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);
|
2009-06-23 04:57:11 +08:00
|
|
|
}
|
2009-03-18 05:15:40 +08:00
|
|
|
|
|
|
|
// Drop the initial value and continue.
|
|
|
|
bool isInvalid = false;
|
|
|
|
if (Value.isInvalid()) {
|
|
|
|
Value = SemaRef.Owned((Expr *)0);
|
|
|
|
isInvalid = true;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
EnumConstantDecl *EnumConst
|
2009-03-18 05:15:40 +08:00
|
|
|
= SemaRef.CheckEnumConstant(Enum, LastEnumConst,
|
|
|
|
EC->getLocation(), EC->getIdentifier(),
|
2010-08-24 07:25:46 +08:00
|
|
|
Value.get());
|
2009-03-18 05:15:40 +08:00
|
|
|
|
|
|
|
if (isInvalid) {
|
|
|
|
if (EnumConst)
|
|
|
|
EnumConst->setInvalidDecl();
|
|
|
|
Enum->setInvalidDecl();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EnumConst) {
|
2012-06-07 04:45:41 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst);
|
2010-10-23 07:36:17 +08:00
|
|
|
|
2010-01-24 06:37:59 +08:00
|
|
|
EnumConst->setAccess(Enum->getAccess());
|
2009-06-30 10:36:12 +08:00
|
|
|
Enum->addDecl(EnumConst);
|
2010-08-21 17:40:31 +08:00
|
|
|
Enumerators.push_back(EnumConst);
|
2009-03-18 05:15:40 +08:00
|
|
|
LastEnumConst = EnumConst;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2012-03-15 07:13:10 +08:00
|
|
|
if (Pattern->getDeclContext()->isFunctionOrMethod() &&
|
|
|
|
!Enum->isScoped()) {
|
2010-03-02 03:00:07 +08:00
|
|
|
// If the enumeration is within a function or method, record the enum
|
|
|
|
// constant as a local.
|
2012-06-07 04:45:41 +08:00
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst);
|
2010-03-02 03:00:07 +08:00
|
|
|
}
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-15 07:13:10 +08:00
|
|
|
// FIXME: Fixup LBraceLoc
|
|
|
|
SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(),
|
|
|
|
Enum->getRBraceLoc(), Enum,
|
2010-08-15 10:27:09 +08:00
|
|
|
Enumerators.data(), Enumerators.size(),
|
2009-08-08 22:36:57 +08:00
|
|
|
0, 0);
|
2009-03-18 05:15:40 +08:00
|
|
|
}
|
|
|
|
|
2009-03-25 23:04:13 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("EnumConstantDecls can only occur within EnumDecls.");
|
2009-03-25 23:04:13 +08:00
|
|
|
}
|
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
2010-03-25 14:39:04 +08:00
|
|
|
bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
|
|
|
|
|
2009-11-01 01:21:17 +08:00
|
|
|
// Create a local instantiation scope for this class template, which
|
|
|
|
// will contain the instantiations of the template parameters.
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(SemaRef);
|
2009-08-20 09:44:21 +08:00
|
|
|
TemplateParameterList *TempParams = D->getTemplateParameters();
|
2009-08-26 06:02:44 +08:00
|
|
|
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!InstParams)
|
2009-08-28 00:57:43 +08:00
|
|
|
return NULL;
|
2009-08-20 09:44:21 +08:00
|
|
|
|
|
|
|
CXXRecordDecl *Pattern = D->getTemplatedDecl();
|
2010-03-25 14:39:04 +08:00
|
|
|
|
|
|
|
// Instantiate the qualifier. We have to do this first in case
|
|
|
|
// we're a friend declaration, because if we are then we need to put
|
|
|
|
// the new declaration in the appropriate context.
|
2011-02-25 10:25:35 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc();
|
|
|
|
if (QualifierLoc) {
|
|
|
|
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
|
|
|
|
TemplateArgs);
|
|
|
|
if (!QualifierLoc)
|
|
|
|
return 0;
|
2010-03-25 14:39:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CXXRecordDecl *PrevDecl = 0;
|
|
|
|
ClassTemplateDecl *PrevClassTemplate = 0;
|
|
|
|
|
2012-01-15 00:38:05 +08:00
|
|
|
if (!isFriend && Pattern->getPreviousDecl()) {
|
2010-11-09 07:29:42 +08:00
|
|
|
DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());
|
|
|
|
if (Found.first != Found.second) {
|
|
|
|
PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first);
|
|
|
|
if (PrevClassTemplate)
|
|
|
|
PrevDecl = PrevClassTemplate->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-25 14:39:04 +08:00
|
|
|
// If this isn't a friend, then it's a member template, in which
|
|
|
|
// case we just want to build the instantiation in the
|
|
|
|
// specialization. If it is a friend, we want to build it in
|
|
|
|
// the appropriate context.
|
|
|
|
DeclContext *DC = Owner;
|
|
|
|
if (isFriend) {
|
2011-02-25 10:25:35 +08:00
|
|
|
if (QualifierLoc) {
|
2010-03-25 14:39:04 +08:00
|
|
|
CXXScopeSpec SS;
|
2011-02-25 10:25:35 +08:00
|
|
|
SS.Adopt(QualifierLoc);
|
2010-03-25 14:39:04 +08:00
|
|
|
DC = SemaRef.computeDeclContext(SS);
|
|
|
|
if (!DC) return 0;
|
|
|
|
} else {
|
|
|
|
DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(),
|
|
|
|
Pattern->getDeclContext(),
|
|
|
|
TemplateArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for a previous declaration of the template in the owning
|
|
|
|
// context.
|
|
|
|
LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(),
|
|
|
|
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
|
|
|
SemaRef.LookupQualifiedName(R, DC);
|
|
|
|
|
|
|
|
if (R.isSingleResult()) {
|
|
|
|
PrevClassTemplate = R.getAsSingle<ClassTemplateDecl>();
|
|
|
|
if (PrevClassTemplate)
|
|
|
|
PrevDecl = PrevClassTemplate->getTemplatedDecl();
|
|
|
|
}
|
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
if (!PrevClassTemplate && QualifierLoc) {
|
2010-03-25 14:39:04 +08:00
|
|
|
SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
|
2010-04-01 07:17:41 +08:00
|
|
|
<< D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
|
2011-02-25 10:25:35 +08:00
|
|
|
<< QualifierLoc.getSourceRange();
|
2010-03-25 14:39:04 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-04-09 02:16:15 +08:00
|
|
|
bool AdoptedPreviousTemplateParams = false;
|
2010-03-25 14:39:04 +08:00
|
|
|
if (PrevClassTemplate) {
|
2010-04-09 02:16:15 +08:00
|
|
|
bool Complain = true;
|
|
|
|
|
|
|
|
// HACK: libstdc++ 4.2.1 contains an ill-formed friend class
|
|
|
|
// template for struct std::tr1::__detail::_Map_base, where the
|
|
|
|
// template parameters of the friend declaration don't match the
|
|
|
|
// template parameters of the original declaration. In this one
|
|
|
|
// case, we don't complain about the ill-formed friend
|
|
|
|
// declaration.
|
2011-10-08 19:31:46 +08:00
|
|
|
if (isFriend && Pattern->getIdentifier() &&
|
2010-04-09 02:16:15 +08:00
|
|
|
Pattern->getIdentifier()->isStr("_Map_base") &&
|
|
|
|
DC->isNamespace() &&
|
|
|
|
cast<NamespaceDecl>(DC)->getIdentifier() &&
|
|
|
|
cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) {
|
|
|
|
DeclContext *DCParent = DC->getParent();
|
|
|
|
if (DCParent->isNamespace() &&
|
|
|
|
cast<NamespaceDecl>(DCParent)->getIdentifier() &&
|
|
|
|
cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) {
|
|
|
|
DeclContext *DCParent2 = DCParent->getParent();
|
|
|
|
if (DCParent2->isNamespace() &&
|
|
|
|
cast<NamespaceDecl>(DCParent2)->getIdentifier() &&
|
|
|
|
cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") &&
|
|
|
|
DCParent2->getParent()->isTranslationUnit())
|
|
|
|
Complain = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-25 14:39:04 +08:00
|
|
|
TemplateParameterList *PrevParams
|
|
|
|
= PrevClassTemplate->getTemplateParameters();
|
|
|
|
|
|
|
|
// Make sure the parameter lists match.
|
|
|
|
if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams,
|
2011-10-08 19:31:46 +08:00
|
|
|
Complain,
|
2010-04-09 02:16:15 +08:00
|
|
|
Sema::TPL_TemplateMatch)) {
|
|
|
|
if (Complain)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
AdoptedPreviousTemplateParams = true;
|
|
|
|
InstParams = PrevParams;
|
|
|
|
}
|
2010-03-25 14:39:04 +08:00
|
|
|
|
|
|
|
// Do some additional validation, then merge default arguments
|
|
|
|
// from the existing declarations.
|
2010-04-09 02:16:15 +08:00
|
|
|
if (!AdoptedPreviousTemplateParams &&
|
|
|
|
SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
|
2010-03-25 14:39:04 +08:00
|
|
|
Sema::TPC_ClassTemplate))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
CXXRecordDecl *RecordInst
|
2010-03-25 14:39:04 +08:00
|
|
|
= CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC,
|
2011-03-09 22:09:51 +08:00
|
|
|
Pattern->getLocStart(), Pattern->getLocation(),
|
|
|
|
Pattern->getIdentifier(), PrevDecl,
|
2009-10-13 07:11:44 +08:00
|
|
|
/*DelayTypeCreation=*/true);
|
2009-08-20 09:44:21 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
if (QualifierLoc)
|
|
|
|
RecordInst->setQualifierInfo(QualifierLoc);
|
2010-03-15 18:12:16 +08:00
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
ClassTemplateDecl *Inst
|
2010-03-25 14:39:04 +08:00
|
|
|
= ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
|
|
|
|
D->getIdentifier(), InstParams, RecordInst,
|
|
|
|
PrevClassTemplate);
|
2009-08-20 09:44:21 +08:00
|
|
|
RecordInst->setDescribedClassTemplate(Inst);
|
2010-04-09 04:25:50 +08:00
|
|
|
|
2010-03-25 14:39:04 +08:00
|
|
|
if (isFriend) {
|
2010-04-09 04:25:50 +08:00
|
|
|
if (PrevClassTemplate)
|
|
|
|
Inst->setAccess(PrevClassTemplate->getAccess());
|
|
|
|
else
|
|
|
|
Inst->setAccess(D->getAccess());
|
|
|
|
|
2010-03-25 14:39:04 +08:00
|
|
|
Inst->setObjectOfFriendDecl(PrevClassTemplate != 0);
|
|
|
|
// TODO: do we want to track the instantiation progeny of this
|
|
|
|
// friend target decl?
|
|
|
|
} else {
|
2009-10-31 05:07:27 +08:00
|
|
|
Inst->setAccess(D->getAccess());
|
2010-11-09 07:29:42 +08:00
|
|
|
if (!PrevClassTemplate)
|
|
|
|
Inst->setInstantiatedFromMemberTemplate(D);
|
2010-03-25 14:39:04 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-13 07:11:44 +08:00
|
|
|
// Trigger creation of the type for the instantiation.
|
2010-03-10 11:28:59 +08:00
|
|
|
SemaRef.Context.getInjectedClassNameType(RecordInst,
|
2010-07-09 02:37:38 +08:00
|
|
|
Inst->getInjectedClassNameSpecialization());
|
2010-04-09 04:25:50 +08:00
|
|
|
|
2009-10-31 06:42:42 +08:00
|
|
|
// Finish handling of friends.
|
2010-03-25 14:39:04 +08:00
|
|
|
if (isFriend) {
|
2012-03-13 11:12:56 +08:00
|
|
|
DC->makeDeclVisibleInContext(Inst);
|
2011-11-26 21:33:46 +08:00
|
|
|
Inst->setLexicalDeclContext(Owner);
|
|
|
|
RecordInst->setLexicalDeclContext(Owner);
|
2009-10-31 05:07:27 +08:00
|
|
|
return Inst;
|
2009-10-31 06:42:42 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-11-26 21:33:46 +08:00
|
|
|
if (D->isOutOfLine()) {
|
|
|
|
Inst->setLexicalDeclContext(D->getLexicalDeclContext());
|
|
|
|
RecordInst->setLexicalDeclContext(D->getLexicalDeclContext());
|
|
|
|
}
|
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
Owner->addDecl(Inst);
|
2010-11-11 03:44:59 +08:00
|
|
|
|
|
|
|
if (!PrevClassTemplate) {
|
|
|
|
// Queue up any out-of-line partial specializations of this member
|
|
|
|
// class template; the client will force their instantiation once
|
|
|
|
// the enclosing class has been instantiated.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
|
2010-11-11 03:44:59 +08:00
|
|
|
D->getPartialSpecializations(PartialSpecs);
|
|
|
|
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
|
|
|
|
if (PartialSpecs[I]->isOutOfLine())
|
|
|
|
OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
|
|
|
|
}
|
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2009-10-08 01:21:34 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D) {
|
2009-10-29 08:04:11 +08:00
|
|
|
ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Lookup the already-instantiated declaration in the instantiation
|
|
|
|
// of the class template and return that.
|
|
|
|
DeclContext::lookup_result Found
|
|
|
|
= Owner->lookup(ClassTemplate->getDeclName());
|
|
|
|
if (Found.first == Found.second)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
ClassTemplateDecl *InstClassTemplate
|
|
|
|
= dyn_cast<ClassTemplateDecl>(*Found.first);
|
|
|
|
if (!InstClassTemplate)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-11-11 03:44:59 +08:00
|
|
|
if (ClassTemplatePartialSpecializationDecl *Result
|
|
|
|
= InstClassTemplate->findPartialSpecInstantiatedFromMember(D))
|
|
|
|
return Result;
|
|
|
|
|
|
|
|
return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D);
|
2009-10-08 01:21:34 +08:00
|
|
|
}
|
|
|
|
|
2009-08-28 00:57:43 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
2009-11-01 01:21:17 +08:00
|
|
|
// Create a local instantiation scope for this function template, which
|
|
|
|
// will contain the instantiations of the template parameters and then get
|
2011-10-08 19:31:46 +08:00
|
|
|
// merged with the local instantiation scope for the function template
|
2009-11-01 01:21:17 +08:00
|
|
|
// itself.
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(SemaRef);
|
2010-05-01 02:55:50 +08:00
|
|
|
|
2009-08-28 00:57:43 +08:00
|
|
|
TemplateParameterList *TempParams = D->getTemplateParameters();
|
|
|
|
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!InstParams)
|
2009-08-28 00:57:43 +08:00
|
|
|
return NULL;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-13 22:39:41 +08:00
|
|
|
FunctionDecl *Instantiated = 0;
|
|
|
|
if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl()))
|
2011-10-08 19:31:46 +08:00
|
|
|
Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod,
|
2009-10-13 22:39:41 +08:00
|
|
|
InstParams));
|
|
|
|
else
|
|
|
|
Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl(
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getTemplatedDecl(),
|
2009-10-13 22:39:41 +08:00
|
|
|
InstParams));
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-13 22:39:41 +08:00
|
|
|
if (!Instantiated)
|
2009-08-28 00:57:43 +08:00
|
|
|
return 0;
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// Link the instantiated function template declaration to the function
|
2009-08-28 00:57:43 +08:00
|
|
|
// template from which it was instantiated.
|
2011-10-08 19:31:46 +08:00
|
|
|
FunctionTemplateDecl *InstTemplate
|
2009-10-13 22:39:41 +08:00
|
|
|
= Instantiated->getDescribedFunctionTemplate();
|
2009-10-13 06:27:17 +08:00
|
|
|
InstTemplate->setAccess(D->getAccess());
|
2011-10-08 19:31:46 +08:00
|
|
|
assert(InstTemplate &&
|
2009-10-13 22:39:41 +08:00
|
|
|
"VisitFunctionDecl/CXXMethodDecl didn't create a template!");
|
2009-12-15 07:19:40 +08:00
|
|
|
|
2010-03-27 07:10:15 +08:00
|
|
|
bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None);
|
|
|
|
|
2009-12-15 07:19:40 +08:00
|
|
|
// Link the instantiation back to the pattern *unless* this is a
|
|
|
|
// non-definition friend declaration.
|
|
|
|
if (!InstTemplate->getInstantiatedFromMemberTemplate() &&
|
2010-03-27 07:10:15 +08:00
|
|
|
!(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition()))
|
2009-10-13 22:39:41 +08:00
|
|
|
InstTemplate->setInstantiatedFromMemberTemplate(D);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-03-27 07:10:15 +08:00
|
|
|
// Make declarations visible in the appropriate context.
|
2012-08-10 11:15:35 +08:00
|
|
|
if (!isFriend) {
|
2009-10-13 22:39:41 +08:00
|
|
|
Owner->addDecl(InstTemplate);
|
2012-08-10 11:15:35 +08:00
|
|
|
} else if (InstTemplate->getDeclContext()->isRecord() &&
|
|
|
|
!D->getPreviousDecl()) {
|
|
|
|
SemaRef.CheckFriendAccess(InstTemplate);
|
|
|
|
}
|
2010-03-27 07:10:15 +08:00
|
|
|
|
2009-08-28 00:57:43 +08:00
|
|
|
return InstTemplate;
|
|
|
|
}
|
|
|
|
|
2009-03-26 05:17:03 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
|
|
|
CXXRecordDecl *PrevDecl = 0;
|
|
|
|
if (D->isInjectedClassName())
|
|
|
|
PrevDecl = cast<CXXRecordDecl>(Owner);
|
2012-01-15 00:38:05 +08:00
|
|
|
else if (D->getPreviousDecl()) {
|
2010-03-01 23:56:25 +08:00
|
|
|
NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(),
|
2012-01-15 00:38:05 +08:00
|
|
|
D->getPreviousDecl(),
|
2009-12-16 06:29:06 +08:00
|
|
|
TemplateArgs);
|
|
|
|
if (!Prev) return 0;
|
|
|
|
PrevDecl = cast<CXXRecordDecl>(Prev);
|
|
|
|
}
|
2009-03-26 05:17:03 +08:00
|
|
|
|
|
|
|
CXXRecordDecl *Record
|
2009-09-09 23:08:12 +08:00
|
|
|
= CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,
|
2011-03-09 22:09:51 +08:00
|
|
|
D->getLocStart(), D->getLocation(),
|
|
|
|
D->getIdentifier(), PrevDecl);
|
2010-03-15 18:12:16 +08:00
|
|
|
|
|
|
|
// Substitute the nested name specifier, if any.
|
|
|
|
if (SubstQualifier(D, Record))
|
|
|
|
return 0;
|
|
|
|
|
2009-03-26 05:17:03 +08:00
|
|
|
Record->setImplicit(D->isImplicit());
|
2009-08-28 03:11:42 +08:00
|
|
|
// FIXME: Check against AS_none is an ugly hack to work around the issue that
|
|
|
|
// the tag decls introduced by friend class declarations don't have an access
|
|
|
|
// specifier. Remove once this area of the code gets sorted out.
|
|
|
|
if (D->getAccess() != AS_none)
|
|
|
|
Record->setAccess(D->getAccess());
|
2009-03-26 05:17:03 +08:00
|
|
|
if (!D->isInjectedClassName())
|
2009-10-08 23:14:33 +08:00
|
|
|
Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
|
2009-03-26 05:17:03 +08:00
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
// If the original function was part of a friend declaration,
|
|
|
|
// inherit its namespace state.
|
|
|
|
if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
|
|
|
|
Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
|
|
|
|
|
2010-05-21 08:31:19 +08:00
|
|
|
// Make sure that anonymous structs and unions are recorded.
|
|
|
|
if (D->isAnonymousStructOrUnion()) {
|
|
|
|
Record->setAnonymousStructOrUnion(true);
|
2010-08-31 08:36:30 +08:00
|
|
|
if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
|
2010-05-21 08:31:19 +08:00
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
|
|
|
|
}
|
2009-09-01 12:26:58 +08:00
|
|
|
|
2009-06-30 10:36:12 +08:00
|
|
|
Owner->addDecl(Record);
|
2009-03-26 05:17:03 +08:00
|
|
|
return Record;
|
|
|
|
}
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
/// Normal class members are of more specific types and therefore
|
|
|
|
/// don't make it here. This function serves two purposes:
|
|
|
|
/// 1) instantiating function templates
|
|
|
|
/// 2) substituting friend declarations
|
|
|
|
/// FIXME: preserve function definitions in case #2
|
2009-12-25 04:56:24 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
2009-10-13 22:39:41 +08:00
|
|
|
TemplateParameterList *TemplateParams) {
|
2009-06-30 04:59:39 +08:00
|
|
|
// Check whether there is already a function template specialization for
|
|
|
|
// this declaration.
|
|
|
|
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
2010-03-27 13:57:59 +08:00
|
|
|
if (FunctionTemplate && !TemplateParams) {
|
2011-10-08 19:31:46 +08:00
|
|
|
std::pair<const TemplateArgument *, unsigned> Innermost
|
2010-07-09 02:37:38 +08:00
|
|
|
= TemplateArgs.getInnermost();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-28 22:34:23 +08:00
|
|
|
void *InsertPos = 0;
|
2010-07-20 21:59:58 +08:00
|
|
|
FunctionDecl *SpecFunc
|
|
|
|
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
|
|
|
|
InsertPos);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-30 04:59:39 +08:00
|
|
|
// If we already have a function template specialization, return it.
|
2010-07-20 21:59:58 +08:00
|
|
|
if (SpecFunc)
|
|
|
|
return SpecFunc;
|
2009-06-30 04:59:39 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-27 13:57:59 +08:00
|
|
|
bool isFriend;
|
|
|
|
if (FunctionTemplate)
|
|
|
|
isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
|
|
|
|
else
|
|
|
|
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
|
|
|
|
|
2010-01-17 04:21:20 +08:00
|
|
|
bool MergeWithParentScope = (TemplateParams != 0) ||
|
2010-05-22 05:25:08 +08:00
|
|
|
Owner->isFunctionOrMethod() ||
|
2011-10-08 19:31:46 +08:00
|
|
|
!(isa<Decl>(Owner) &&
|
2010-01-17 04:21:20 +08:00
|
|
|
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ParmVarDecl *, 4> Params;
|
2011-11-10 13:42:04 +08:00
|
|
|
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
|
2010-03-11 17:03:00 +08:00
|
|
|
if (!TInfo)
|
2009-03-24 07:06:20 +08:00
|
|
|
return 0;
|
2010-03-11 17:03:00 +08:00
|
|
|
QualType T = TInfo->getType();
|
2009-08-14 10:03:10 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
|
|
|
|
if (QualifierLoc) {
|
|
|
|
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
|
|
|
|
TemplateArgs);
|
|
|
|
if (!QualifierLoc)
|
|
|
|
return 0;
|
2010-03-26 12:53:08 +08:00
|
|
|
}
|
|
|
|
|
2010-02-06 09:50:47 +08:00
|
|
|
// If we're instantiating a local function declaration, put the result
|
|
|
|
// in the owner; otherwise we need to find the instantiated context.
|
|
|
|
DeclContext *DC;
|
|
|
|
if (D->getDeclContext()->isFunctionOrMethod())
|
|
|
|
DC = Owner;
|
2011-02-25 10:25:35 +08:00
|
|
|
else if (isFriend && QualifierLoc) {
|
2010-03-26 12:53:08 +08:00
|
|
|
CXXScopeSpec SS;
|
2011-02-25 10:25:35 +08:00
|
|
|
SS.Adopt(QualifierLoc);
|
2010-03-26 12:53:08 +08:00
|
|
|
DC = SemaRef.computeDeclContext(SS);
|
|
|
|
if (!DC) return 0;
|
|
|
|
} else {
|
2011-10-08 19:31:46 +08:00
|
|
|
DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(),
|
2010-03-01 23:56:25 +08:00
|
|
|
TemplateArgs);
|
2010-03-26 12:53:08 +08:00
|
|
|
}
|
2010-02-06 09:50:47 +08:00
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
FunctionDecl *Function =
|
2011-03-08 16:55:46 +08:00
|
|
|
FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
|
|
|
|
D->getLocation(), D->getDeclName(), T, TInfo,
|
2010-04-20 06:54:31 +08:00
|
|
|
D->getStorageClass(), D->getStorageClassAsWritten(),
|
2011-08-16 05:04:07 +08:00
|
|
|
D->isInlineSpecified(), D->hasWrittenPrototype(),
|
2012-02-13 11:54:03 +08:00
|
|
|
D->isConstexpr());
|
2010-03-15 18:12:16 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
if (QualifierLoc)
|
|
|
|
Function->setQualifierInfo(QualifierLoc);
|
2010-03-15 18:12:16 +08:00
|
|
|
|
2010-03-27 07:10:15 +08:00
|
|
|
DeclContext *LexicalDC = Owner;
|
|
|
|
if (!isFriend && D->isOutOfLine()) {
|
|
|
|
assert(D->getDeclContext()->isFileContext());
|
|
|
|
LexicalDC = D->getDeclContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
Function->setLexicalDeclContext(LexicalDC);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
// Attach the parameters
|
2011-07-06 02:30:26 +08:00
|
|
|
if (isa<FunctionProtoType>(Function->getType().IgnoreParens())) {
|
2011-06-23 02:16:25 +08:00
|
|
|
// Adopt the already-instantiated parameters into our own context.
|
|
|
|
for (unsigned P = 0; P < Params.size(); ++P)
|
|
|
|
if (Params[P])
|
|
|
|
Params[P]->setOwningFunction(Function);
|
|
|
|
} else {
|
|
|
|
// Since we were instantiated via a typedef of a function type, create
|
|
|
|
// new parameters.
|
|
|
|
const FunctionProtoType *Proto
|
|
|
|
= Function->getType()->getAs<FunctionProtoType>();
|
|
|
|
assert(Proto && "No function prototype in template instantiation?");
|
|
|
|
for (FunctionProtoType::arg_type_iterator AI = Proto->arg_type_begin(),
|
|
|
|
AE = Proto->arg_type_end(); AI != AE; ++AI) {
|
|
|
|
ParmVarDecl *Param
|
|
|
|
= SemaRef.BuildParmVarDeclForTypedef(Function, Function->getLocation(),
|
|
|
|
*AI);
|
|
|
|
Param->setScopeInfo(0, Params.size());
|
|
|
|
Params.push_back(Param);
|
|
|
|
}
|
|
|
|
}
|
2011-09-22 02:16:56 +08:00
|
|
|
Function->setParams(Params);
|
2009-08-28 15:59:38 +08:00
|
|
|
|
2010-05-18 00:38:00 +08:00
|
|
|
SourceLocation InstantiateAtPOI;
|
2009-10-13 22:39:41 +08:00
|
|
|
if (TemplateParams) {
|
|
|
|
// Our resulting instantiation is actually a function template, since we
|
|
|
|
// are substituting only the outer template parameters. For example, given
|
|
|
|
//
|
|
|
|
// template<typename T>
|
|
|
|
// struct X {
|
|
|
|
// template<typename U> friend void f(T, U);
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// X<int> x;
|
|
|
|
//
|
2011-10-08 19:31:46 +08:00
|
|
|
// We are instantiating the friend function template "f" within X<int>,
|
2009-10-13 22:39:41 +08:00
|
|
|
// which means substituting int for T, but leaving "f" as a friend function
|
|
|
|
// template.
|
|
|
|
// Build the function template itself.
|
2010-03-26 12:53:08 +08:00
|
|
|
FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC,
|
2009-10-13 22:39:41 +08:00
|
|
|
Function->getLocation(),
|
|
|
|
Function->getDeclName(),
|
|
|
|
TemplateParams, Function);
|
|
|
|
Function->setDescribedFunctionTemplate(FunctionTemplate);
|
2010-03-27 07:10:15 +08:00
|
|
|
|
|
|
|
FunctionTemplate->setLexicalDeclContext(LexicalDC);
|
2010-03-26 12:53:08 +08:00
|
|
|
|
|
|
|
if (isFriend && D->isThisDeclarationADefinition()) {
|
|
|
|
// TODO: should we remember this connection regardless of whether
|
|
|
|
// the friend declaration provided a body?
|
|
|
|
FunctionTemplate->setInstantiatedFromMemberTemplate(
|
|
|
|
D->getDescribedFunctionTemplate());
|
|
|
|
}
|
2009-11-14 09:20:54 +08:00
|
|
|
} else if (FunctionTemplate) {
|
|
|
|
// Record this function template specialization.
|
2011-10-08 19:31:46 +08:00
|
|
|
std::pair<const TemplateArgument *, unsigned> Innermost
|
2010-07-09 02:37:38 +08:00
|
|
|
= TemplateArgs.getInnermost();
|
2010-02-11 09:19:42 +08:00
|
|
|
Function->setFunctionTemplateSpecialization(FunctionTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgumentList::CreateCopy(SemaRef.Context,
|
2010-07-09 02:37:38 +08:00
|
|
|
Innermost.first,
|
|
|
|
Innermost.second),
|
2012-03-28 22:34:23 +08:00
|
|
|
/*InsertPos=*/0);
|
2011-08-18 17:09:59 +08:00
|
|
|
} else if (isFriend) {
|
|
|
|
// Note, we need this connection even if the friend doesn't have a body.
|
|
|
|
// Its body may exist but not have been attached yet due to deferred
|
|
|
|
// parsing.
|
|
|
|
// FIXME: It might be cleaner to set this when attaching the body to the
|
|
|
|
// friend function declaration, however that would require finding all the
|
|
|
|
// instantiations and modifying them.
|
2010-03-26 12:53:08 +08:00
|
|
|
Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
|
2009-08-28 15:59:38 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
if (InitFunctionInstantiation(Function, D))
|
|
|
|
Function->setInvalidDecl();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-04-08 17:05:18 +08:00
|
|
|
bool isExplicitSpecialization = false;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-19 06:49:29 +08:00
|
|
|
LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
|
|
|
|
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
|
|
|
|
2010-04-08 17:05:18 +08:00
|
|
|
if (DependentFunctionTemplateSpecializationInfo *Info
|
|
|
|
= D->getDependentSpecializationInfo()) {
|
|
|
|
assert(isFriend && "non-friend has dependent specialization info?");
|
|
|
|
|
|
|
|
// This needs to be set now for future sanity.
|
|
|
|
Function->setObjectOfFriendDecl(/*HasPrevious*/ true);
|
|
|
|
|
|
|
|
// Instantiate the explicit template arguments.
|
|
|
|
TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
|
|
|
|
Info->getRAngleLoc());
|
2010-12-23 05:19:48 +08:00
|
|
|
if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
|
|
|
|
ExplicitArgs, TemplateArgs))
|
|
|
|
return 0;
|
2010-04-08 17:05:18 +08:00
|
|
|
|
|
|
|
// Map the candidate templates to their instantiations.
|
|
|
|
for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
|
|
|
|
Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
|
|
|
|
Info->getTemplate(I),
|
|
|
|
TemplateArgs);
|
|
|
|
if (!Temp) return 0;
|
|
|
|
|
|
|
|
Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SemaRef.CheckFunctionTemplateSpecialization(Function,
|
|
|
|
&ExplicitArgs,
|
|
|
|
Previous))
|
|
|
|
Function->setInvalidDecl();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-04-08 17:05:18 +08:00
|
|
|
isExplicitSpecialization = true;
|
|
|
|
|
|
|
|
} else if (TemplateParams || !FunctionTemplate) {
|
2011-10-08 19:31:46 +08:00
|
|
|
// Look only into the namespace where the friend would be declared to
|
|
|
|
// find a previous declaration. This is the innermost enclosing namespace,
|
2009-10-13 22:39:41 +08:00
|
|
|
// as described in ActOnFriendFunctionDecl.
|
2009-11-19 06:49:29 +08:00
|
|
|
SemaRef.LookupQualifiedName(Previous, DC);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-13 22:39:41 +08:00
|
|
|
// In C++, the previous declaration we find might be a tag type
|
|
|
|
// (class or enum). In this case, the new declaration will hide the
|
|
|
|
// tag type. Note that this does does not apply if we're declaring a
|
|
|
|
// typedef (C++ [dcl.typedef]p4).
|
2009-11-19 06:49:29 +08:00
|
|
|
if (Previous.isSingleTagDecl())
|
|
|
|
Previous.clear();
|
2009-10-13 22:39:41 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-12-10 17:41:52 +08:00
|
|
|
SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
|
2011-10-11 08:28:45 +08:00
|
|
|
isExplicitSpecialization);
|
2009-06-26 06:08:12 +08:00
|
|
|
|
2010-04-24 09:30:58 +08:00
|
|
|
NamedDecl *PrincipalDecl = (TemplateParams
|
|
|
|
? cast<NamedDecl>(FunctionTemplate)
|
|
|
|
: Function);
|
|
|
|
|
2009-10-13 22:39:41 +08:00
|
|
|
// If the original function was part of a friend declaration,
|
|
|
|
// inherit its namespace state and add it to the owner.
|
2010-03-26 12:53:08 +08:00
|
|
|
if (isFriend) {
|
2009-11-19 06:49:29 +08:00
|
|
|
NamedDecl *PrevDecl;
|
2010-04-24 09:30:58 +08:00
|
|
|
if (TemplateParams)
|
2012-01-15 00:38:05 +08:00
|
|
|
PrevDecl = FunctionTemplate->getPreviousDecl();
|
2010-04-24 09:30:58 +08:00
|
|
|
else
|
2012-01-15 00:38:05 +08:00
|
|
|
PrevDecl = Function->getPreviousDecl();
|
2010-04-24 09:30:58 +08:00
|
|
|
|
|
|
|
PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
|
2012-03-13 11:12:56 +08:00
|
|
|
DC->makeDeclVisibleInContext(PrincipalDecl);
|
2010-08-31 05:10:05 +08:00
|
|
|
|
2010-08-31 06:25:56 +08:00
|
|
|
bool queuedInstantiation = false;
|
2010-08-31 05:10:05 +08:00
|
|
|
|
2011-10-19 08:54:10 +08:00
|
|
|
// C++98 [temp.friend]p5: When a function is defined in a friend function
|
|
|
|
// declaration in a class template, the function is defined at each
|
|
|
|
// instantiation of the class template. The function is defined even if it
|
|
|
|
// is never used.
|
|
|
|
// C++11 [temp.friend]p4: When a function is defined in a friend function
|
|
|
|
// declaration in a class template, the function is instantiated when the
|
|
|
|
// function is odr-used.
|
|
|
|
//
|
|
|
|
// If -Wc++98-compat is enabled, we go through the motions of checking for a
|
|
|
|
// redefinition, but don't instantiate the function.
|
2012-03-11 15:00:24 +08:00
|
|
|
if ((!SemaRef.getLangOpts().CPlusPlus0x ||
|
2011-10-19 08:54:10 +08:00
|
|
|
SemaRef.Diags.getDiagnosticLevel(
|
|
|
|
diag::warn_cxx98_compat_friend_redefinition,
|
|
|
|
Function->getLocation())
|
|
|
|
!= DiagnosticsEngine::Ignored) &&
|
2010-05-18 13:45:02 +08:00
|
|
|
D->isThisDeclarationADefinition()) {
|
|
|
|
// Check for a function body.
|
|
|
|
const FunctionDecl *Definition = 0;
|
2011-05-07 04:44:56 +08:00
|
|
|
if (Function->isDefined(Definition) &&
|
2010-05-18 13:45:02 +08:00
|
|
|
Definition->getTemplateSpecializationKind() == TSK_Undeclared) {
|
2011-10-19 08:54:10 +08:00
|
|
|
SemaRef.Diag(Function->getLocation(),
|
2012-03-11 15:00:24 +08:00
|
|
|
SemaRef.getLangOpts().CPlusPlus0x ?
|
2011-10-19 08:54:10 +08:00
|
|
|
diag::warn_cxx98_compat_friend_redefinition :
|
|
|
|
diag::err_redefinition) << Function->getDeclName();
|
2010-05-18 13:45:02 +08:00
|
|
|
SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition);
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!SemaRef.getLangOpts().CPlusPlus0x)
|
2011-10-19 08:54:10 +08:00
|
|
|
Function->setInvalidDecl();
|
2011-10-08 19:31:46 +08:00
|
|
|
}
|
2010-05-18 13:45:02 +08:00
|
|
|
// Check for redefinitions due to other instantiations of this or
|
|
|
|
// a similar friend function.
|
|
|
|
else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(),
|
|
|
|
REnd = Function->redecls_end();
|
|
|
|
R != REnd; ++R) {
|
2010-08-28 23:42:30 +08:00
|
|
|
if (*R == Function)
|
|
|
|
continue;
|
2010-08-31 05:10:05 +08:00
|
|
|
switch (R->getFriendObjectKind()) {
|
|
|
|
case Decl::FOK_None:
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!SemaRef.getLangOpts().CPlusPlus0x &&
|
2011-10-19 08:54:10 +08:00
|
|
|
!queuedInstantiation && R->isUsed(false)) {
|
2010-08-31 05:10:05 +08:00
|
|
|
if (MemberSpecializationInfo *MSInfo
|
|
|
|
= Function->getMemberSpecializationInfo()) {
|
|
|
|
if (MSInfo->getPointOfInstantiation().isInvalid()) {
|
|
|
|
SourceLocation Loc = R->getLocation(); // FIXME
|
|
|
|
MSInfo->setPointOfInstantiation(Loc);
|
|
|
|
SemaRef.PendingLocalImplicitInstantiations.push_back(
|
|
|
|
std::make_pair(Function, Loc));
|
|
|
|
queuedInstantiation = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2010-05-18 13:45:02 +08:00
|
|
|
if (const FunctionDecl *RPattern
|
2010-08-28 23:46:56 +08:00
|
|
|
= R->getTemplateInstantiationPattern())
|
2011-05-07 04:44:56 +08:00
|
|
|
if (RPattern->isDefined(RPattern)) {
|
2011-10-19 08:54:10 +08:00
|
|
|
SemaRef.Diag(Function->getLocation(),
|
2012-03-11 15:00:24 +08:00
|
|
|
SemaRef.getLangOpts().CPlusPlus0x ?
|
2011-10-19 08:54:10 +08:00
|
|
|
diag::warn_cxx98_compat_friend_redefinition :
|
|
|
|
diag::err_redefinition)
|
2010-05-18 13:45:02 +08:00
|
|
|
<< Function->getDeclName();
|
2010-08-28 23:46:56 +08:00
|
|
|
SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
|
2012-03-11 15:00:24 +08:00
|
|
|
if (!SemaRef.getLangOpts().CPlusPlus0x)
|
2011-10-19 08:54:10 +08:00
|
|
|
Function->setInvalidDecl();
|
2010-05-18 13:45:02 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-13 22:39:41 +08:00
|
|
|
}
|
|
|
|
|
2010-04-24 09:30:58 +08:00
|
|
|
if (Function->isOverloadedOperator() && !DC->isRecord() &&
|
|
|
|
PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary))
|
|
|
|
PrincipalDecl->setNonMemberOperator();
|
|
|
|
|
2011-05-24 05:07:59 +08:00
|
|
|
assert(!D->isDefaulted() && "only methods should be defaulted");
|
2009-06-26 06:08:12 +08:00
|
|
|
return Function;
|
|
|
|
}
|
2009-03-24 07:06:20 +08:00
|
|
|
|
2009-08-28 00:57:43 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
2011-08-14 11:52:19 +08:00
|
|
|
TemplateParameterList *TemplateParams,
|
|
|
|
bool IsClassScopeSpecialization) {
|
2009-08-21 08:16:32 +08:00
|
|
|
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
2009-08-28 00:57:43 +08:00
|
|
|
if (FunctionTemplate && !TemplateParams) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// We are creating a function template specialization from a function
|
|
|
|
// template. Check whether there is already a function template
|
2009-08-28 00:57:43 +08:00
|
|
|
// specialization for this particular set of template arguments.
|
2011-10-08 19:31:46 +08:00
|
|
|
std::pair<const TemplateArgument *, unsigned> Innermost
|
2010-07-09 02:37:38 +08:00
|
|
|
= TemplateArgs.getInnermost();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-28 22:34:23 +08:00
|
|
|
void *InsertPos = 0;
|
2010-07-20 21:59:58 +08:00
|
|
|
FunctionDecl *SpecFunc
|
|
|
|
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
|
|
|
|
InsertPos);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-21 08:16:32 +08:00
|
|
|
// If we already have a function template specialization, return it.
|
2010-07-20 21:59:58 +08:00
|
|
|
if (SpecFunc)
|
|
|
|
return SpecFunc;
|
2009-08-21 08:16:32 +08:00
|
|
|
}
|
|
|
|
|
2010-03-27 13:57:59 +08:00
|
|
|
bool isFriend;
|
|
|
|
if (FunctionTemplate)
|
|
|
|
isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None);
|
|
|
|
else
|
|
|
|
isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
|
|
|
|
|
2010-01-17 04:21:20 +08:00
|
|
|
bool MergeWithParentScope = (TemplateParams != 0) ||
|
2011-10-08 19:31:46 +08:00
|
|
|
!(isa<Decl>(Owner) &&
|
2010-01-17 04:21:20 +08:00
|
|
|
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
|
2009-05-15 05:44:34 +08:00
|
|
|
|
2010-10-19 10:26:41 +08:00
|
|
|
// Instantiate enclosing template arguments for friends.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateParameterList *, 4> TempParamLists;
|
2010-10-19 10:26:41 +08:00
|
|
|
unsigned NumTempParamLists = 0;
|
|
|
|
if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) {
|
|
|
|
TempParamLists.set_size(NumTempParamLists);
|
|
|
|
for (unsigned I = 0; I != NumTempParamLists; ++I) {
|
|
|
|
TemplateParameterList *TempParams = D->getTemplateParameterList(I);
|
|
|
|
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
|
|
|
|
if (!InstParams)
|
|
|
|
return NULL;
|
|
|
|
TempParamLists[I] = InstParams;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ParmVarDecl *, 4> Params;
|
2012-01-20 22:42:32 +08:00
|
|
|
TypeSourceInfo *TInfo = SubstFunctionType(D, Params);
|
2010-03-11 17:03:00 +08:00
|
|
|
if (!TInfo)
|
2009-03-24 07:06:20 +08:00
|
|
|
return 0;
|
2010-03-11 17:03:00 +08:00
|
|
|
QualType T = TInfo->getType();
|
2009-03-24 07:06:20 +08:00
|
|
|
|
2010-12-15 06:11:44 +08:00
|
|
|
// \brief If the type of this function, after ignoring parentheses,
|
|
|
|
// is not *directly* a function type, then we're instantiating a function
|
|
|
|
// that was declared via a typedef, e.g.,
|
2010-05-05 02:18:31 +08:00
|
|
|
//
|
|
|
|
// typedef int functype(int, int);
|
|
|
|
// functype func;
|
|
|
|
//
|
|
|
|
// In this case, we'll just go instantiate the ParmVarDecls that we
|
|
|
|
// synthesized in the method declaration.
|
2010-12-15 06:11:44 +08:00
|
|
|
if (!isa<FunctionProtoType>(T.IgnoreParens())) {
|
2010-05-05 02:18:31 +08:00
|
|
|
assert(!Params.size() && "Instantiating type could not yield parameters");
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<QualType, 4> ParamTypes;
|
2011-10-08 19:31:46 +08:00
|
|
|
if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
|
|
|
|
D->getNumParams(), TemplateArgs, ParamTypes,
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-08 00:43:16 +08:00
|
|
|
&Params))
|
2011-10-08 19:31:46 +08:00
|
|
|
return 0;
|
2010-05-05 02:18:31 +08:00
|
|
|
}
|
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
|
|
|
|
if (QualifierLoc) {
|
|
|
|
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
|
2010-03-27 13:57:59 +08:00
|
|
|
TemplateArgs);
|
2011-10-08 19:31:46 +08:00
|
|
|
if (!QualifierLoc)
|
2011-02-25 10:25:35 +08:00
|
|
|
return 0;
|
2010-03-27 13:57:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DeclContext *DC = Owner;
|
|
|
|
if (isFriend) {
|
2011-02-25 10:25:35 +08:00
|
|
|
if (QualifierLoc) {
|
2010-03-27 13:57:59 +08:00
|
|
|
CXXScopeSpec SS;
|
2011-02-25 10:25:35 +08:00
|
|
|
SS.Adopt(QualifierLoc);
|
2010-03-27 13:57:59 +08:00
|
|
|
DC = SemaRef.computeDeclContext(SS);
|
2010-10-19 13:01:53 +08:00
|
|
|
|
|
|
|
if (DC && SemaRef.RequireCompleteDeclContext(SS, DC))
|
|
|
|
return 0;
|
2010-03-27 13:57:59 +08:00
|
|
|
} else {
|
|
|
|
DC = SemaRef.FindInstantiatedContext(D->getLocation(),
|
|
|
|
D->getDeclContext(),
|
|
|
|
TemplateArgs);
|
|
|
|
}
|
|
|
|
if (!DC) return 0;
|
|
|
|
}
|
|
|
|
|
2009-03-24 07:06:20 +08:00
|
|
|
// Build the instantiated method declaration.
|
2010-03-27 13:57:59 +08:00
|
|
|
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
|
2009-08-22 02:42:58 +08:00
|
|
|
CXXMethodDecl *Method = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-03-08 16:55:46 +08:00
|
|
|
SourceLocation StartLoc = D->getInnerLocStart();
|
2010-08-12 06:01:17 +08:00
|
|
|
DeclarationNameInfo NameInfo
|
|
|
|
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
|
2009-08-22 06:43:28 +08:00
|
|
|
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
|
2011-03-08 16:55:46 +08:00
|
|
|
StartLoc, NameInfo, T, TInfo,
|
2009-09-09 23:08:12 +08:00
|
|
|
Constructor->isExplicit(),
|
2010-04-20 06:54:31 +08:00
|
|
|
Constructor->isInlineSpecified(),
|
2012-02-13 11:54:03 +08:00
|
|
|
false, Constructor->isConstexpr());
|
2009-08-22 06:43:28 +08:00
|
|
|
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
|
|
|
|
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
|
2011-03-08 16:55:46 +08:00
|
|
|
StartLoc, NameInfo, T, TInfo,
|
2010-08-12 06:01:17 +08:00
|
|
|
Destructor->isInlineSpecified(),
|
2010-04-20 06:54:31 +08:00
|
|
|
false);
|
2009-08-22 07:19:43 +08:00
|
|
|
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
|
|
|
|
Method = CXXConversionDecl::Create(SemaRef.Context, Record,
|
2011-03-08 16:55:46 +08:00
|
|
|
StartLoc, NameInfo, T, TInfo,
|
2009-10-28 05:01:01 +08:00
|
|
|
Conversion->isInlineSpecified(),
|
2011-03-09 01:10:18 +08:00
|
|
|
Conversion->isExplicit(),
|
2012-02-13 11:54:03 +08:00
|
|
|
Conversion->isConstexpr(),
|
2011-10-01 10:31:28 +08:00
|
|
|
Conversion->getLocEnd());
|
2009-08-22 02:42:58 +08:00
|
|
|
} else {
|
2010-08-12 06:01:17 +08:00
|
|
|
Method = CXXMethodDecl::Create(SemaRef.Context, Record,
|
2011-03-08 16:55:46 +08:00
|
|
|
StartLoc, NameInfo, T, TInfo,
|
2010-04-20 06:54:31 +08:00
|
|
|
D->isStatic(),
|
|
|
|
D->getStorageClassAsWritten(),
|
2011-03-09 01:10:18 +08:00
|
|
|
D->isInlineSpecified(),
|
2012-02-13 11:54:03 +08:00
|
|
|
D->isConstexpr(), D->getLocEnd());
|
2009-08-22 02:42:58 +08:00
|
|
|
}
|
2009-08-21 08:16:32 +08:00
|
|
|
|
2011-02-25 10:25:35 +08:00
|
|
|
if (QualifierLoc)
|
|
|
|
Method->setQualifierInfo(QualifierLoc);
|
2010-03-15 18:12:16 +08:00
|
|
|
|
2009-08-28 00:57:43 +08:00
|
|
|
if (TemplateParams) {
|
|
|
|
// Our resulting instantiation is actually a function template, since we
|
|
|
|
// are substituting only the outer template parameters. For example, given
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2009-08-28 00:57:43 +08:00
|
|
|
// template<typename T>
|
|
|
|
// struct X {
|
|
|
|
// template<typename U> void f(T, U);
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// X<int> x;
|
|
|
|
//
|
|
|
|
// We are instantiating the member template "f" within X<int>, which means
|
|
|
|
// substituting int for T, but leaving "f" as a member function template.
|
|
|
|
// Build the function template itself.
|
|
|
|
FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record,
|
|
|
|
Method->getLocation(),
|
2009-09-09 23:08:12 +08:00
|
|
|
Method->getDeclName(),
|
2009-08-28 00:57:43 +08:00
|
|
|
TemplateParams, Method);
|
2010-03-27 13:57:59 +08:00
|
|
|
if (isFriend) {
|
|
|
|
FunctionTemplate->setLexicalDeclContext(Owner);
|
|
|
|
FunctionTemplate->setObjectOfFriendDecl(true);
|
|
|
|
} else if (D->isOutOfLine())
|
2009-09-09 23:08:12 +08:00
|
|
|
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
|
2009-08-28 00:57:43 +08:00
|
|
|
Method->setDescribedFunctionTemplate(FunctionTemplate);
|
2009-11-14 09:20:54 +08:00
|
|
|
} else if (FunctionTemplate) {
|
|
|
|
// Record this function template specialization.
|
2011-10-08 19:31:46 +08:00
|
|
|
std::pair<const TemplateArgument *, unsigned> Innermost
|
2010-07-09 02:37:38 +08:00
|
|
|
= TemplateArgs.getInnermost();
|
2010-02-11 09:19:42 +08:00
|
|
|
Method->setFunctionTemplateSpecialization(FunctionTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
TemplateArgumentList::CreateCopy(SemaRef.Context,
|
|
|
|
Innermost.first,
|
|
|
|
Innermost.second),
|
2012-03-28 22:34:23 +08:00
|
|
|
/*InsertPos=*/0);
|
2010-03-27 13:57:59 +08:00
|
|
|
} else if (!isFriend) {
|
2009-11-14 09:20:54 +08:00
|
|
|
// Record that this is an instantiation of a member function.
|
2009-10-08 07:56:10 +08:00
|
|
|
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
|
2009-11-14 09:20:54 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// If we are instantiating a member function defined
|
2009-07-25 04:34:43 +08:00
|
|
|
// out-of-line, the instantiation will have the same lexical
|
|
|
|
// context (which will be a namespace scope) as the template.
|
2010-03-27 13:57:59 +08:00
|
|
|
if (isFriend) {
|
2010-10-19 10:26:41 +08:00
|
|
|
if (NumTempParamLists)
|
|
|
|
Method->setTemplateParameterListsInfo(SemaRef.Context,
|
|
|
|
NumTempParamLists,
|
|
|
|
TempParamLists.data());
|
|
|
|
|
2010-03-27 13:57:59 +08:00
|
|
|
Method->setLexicalDeclContext(Owner);
|
|
|
|
Method->setObjectOfFriendDecl(true);
|
|
|
|
} else if (D->isOutOfLine())
|
2009-07-25 04:34:43 +08:00
|
|
|
Method->setLexicalDeclContext(D->getLexicalDeclContext());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-24 08:38:23 +08:00
|
|
|
// Attach the parameters
|
|
|
|
for (unsigned P = 0; P < Params.size(); ++P)
|
|
|
|
Params[P]->setOwningFunction(Method);
|
2011-09-22 02:16:56 +08:00
|
|
|
Method->setParams(Params);
|
2009-03-24 08:38:23 +08:00
|
|
|
|
|
|
|
if (InitMethodInstantiation(Method, D))
|
|
|
|
Method->setInvalidDecl();
|
2009-03-24 07:06:20 +08:00
|
|
|
|
2010-08-12 06:01:17 +08:00
|
|
|
LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
|
|
|
|
Sema::ForRedeclaration);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-03-27 13:57:59 +08:00
|
|
|
if (!FunctionTemplate || TemplateParams || isFriend) {
|
|
|
|
SemaRef.LookupQualifiedName(Previous, Record);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-22 02:42:58 +08:00
|
|
|
// In C++, the previous declaration we find might be a tag type
|
|
|
|
// (class or enum). In this case, the new declaration will hide the
|
|
|
|
// tag type. Note that this does does not apply if we're declaring a
|
|
|
|
// typedef (C++ [dcl.typedef]p4).
|
2009-11-19 06:49:29 +08:00
|
|
|
if (Previous.isSingleTagDecl())
|
|
|
|
Previous.clear();
|
2009-08-22 02:42:58 +08:00
|
|
|
}
|
2009-03-24 07:06:20 +08:00
|
|
|
|
2011-08-14 11:52:19 +08:00
|
|
|
if (!IsClassScopeSpecialization)
|
2011-10-11 08:28:45 +08:00
|
|
|
SemaRef.CheckFunctionDeclaration(0, Method, Previous, false);
|
2009-08-22 07:19:43 +08:00
|
|
|
|
2009-12-02 01:24:26 +08:00
|
|
|
if (D->isPure())
|
|
|
|
SemaRef.CheckPureMethod(Method, SourceRange());
|
|
|
|
|
2012-08-10 11:15:35 +08:00
|
|
|
// Propagate access. For a non-friend declaration, the access is
|
|
|
|
// whatever we're propagating from. For a friend, it should be the
|
|
|
|
// previous declaration we just found.
|
|
|
|
if (isFriend && Method->getPreviousDecl())
|
|
|
|
Method->setAccess(Method->getPreviousDecl()->getAccess());
|
|
|
|
else
|
|
|
|
Method->setAccess(D->getAccess());
|
|
|
|
if (FunctionTemplate)
|
|
|
|
FunctionTemplate->setAccess(Method->getAccess());
|
2010-01-21 05:53:11 +08:00
|
|
|
|
2011-01-20 14:52:44 +08:00
|
|
|
SemaRef.CheckOverrideControl(Method);
|
|
|
|
|
2011-11-16 06:39:08 +08:00
|
|
|
// If a function is defined as defaulted or deleted, mark it as such now.
|
|
|
|
if (D->isDefaulted())
|
|
|
|
Method->setDefaulted();
|
|
|
|
if (D->isDeletedAsWritten())
|
|
|
|
Method->setDeletedAsWritten();
|
|
|
|
|
2012-08-10 11:15:35 +08:00
|
|
|
// If there's a function template, let our caller handle it.
|
2010-03-27 13:57:59 +08:00
|
|
|
if (FunctionTemplate) {
|
2012-08-10 11:15:35 +08:00
|
|
|
// do nothing
|
|
|
|
|
|
|
|
// Don't hide a (potentially) valid declaration with an invalid one.
|
2010-03-27 13:57:59 +08:00
|
|
|
} else if (Method->isInvalidDecl() && !Previous.empty()) {
|
2012-08-10 11:15:35 +08:00
|
|
|
// do nothing
|
|
|
|
|
|
|
|
// Otherwise, check access to friends and make them visible.
|
|
|
|
} else if (isFriend) {
|
|
|
|
// We only need to re-check access for methods which we didn't
|
|
|
|
// manage to match during parsing.
|
|
|
|
if (!D->getPreviousDecl())
|
|
|
|
SemaRef.CheckFriendAccess(Method);
|
|
|
|
|
|
|
|
Record->makeDeclVisibleInContext(Method);
|
|
|
|
|
|
|
|
// Otherwise, add the declaration. We don't need to do this for
|
|
|
|
// class-scope specializations because we'll have matched them with
|
|
|
|
// the appropriate template.
|
|
|
|
} else if (!IsClassScopeSpecialization) {
|
|
|
|
Owner->addDecl(Method);
|
2010-03-27 13:57:59 +08:00
|
|
|
}
|
2011-05-24 05:07:59 +08:00
|
|
|
|
|
|
|
if (D->isExplicitlyDefaulted()) {
|
|
|
|
SemaRef.SetDeclDefaulted(Method, Method->getLocation());
|
|
|
|
} else {
|
|
|
|
assert(!D->isDefaulted() &&
|
|
|
|
"should not implicitly default uninstantiated function");
|
|
|
|
}
|
|
|
|
|
2009-03-24 07:06:20 +08:00
|
|
|
return Method;
|
|
|
|
}
|
|
|
|
|
2009-03-25 00:43:20 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
|
2009-08-22 02:42:58 +08:00
|
|
|
return VisitCXXMethodDecl(D);
|
2009-03-25 00:43:20 +08:00
|
|
|
}
|
|
|
|
|
2009-03-24 08:15:49 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
|
2009-08-22 06:43:28 +08:00
|
|
|
return VisitCXXMethodDecl(D);
|
2009-03-24 08:15:49 +08:00
|
|
|
}
|
|
|
|
|
2009-03-25 08:34:44 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
|
2009-08-22 07:19:43 +08:00
|
|
|
return VisitCXXMethodDecl(D);
|
2009-03-25 08:34:44 +08:00
|
|
|
}
|
|
|
|
|
2009-03-25 23:04:13 +08:00
|
|
|
ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {
|
2011-05-02 06:35:37 +08:00
|
|
|
return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0,
|
2012-01-26 00:15:54 +08:00
|
|
|
llvm::Optional<unsigned>(),
|
|
|
|
/*ExpectParameterPack=*/false);
|
2009-03-24 07:06:20 +08:00
|
|
|
}
|
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
|
|
|
|
TemplateTypeParmDecl *D) {
|
|
|
|
// TODO: don't always clone when decls are refcounted.
|
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
|
|
|
assert(D->getTypeForDecl()->isTemplateTypeParmType());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
TemplateTypeParmDecl *Inst =
|
2011-03-06 23:48:19 +08:00
|
|
|
TemplateTypeParmDecl::Create(SemaRef.Context, Owner,
|
|
|
|
D->getLocStart(), D->getLocation(),
|
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
|
|
|
D->getDepth() - TemplateArgs.getNumLevels(),
|
|
|
|
D->getIndex(), D->getIdentifier(),
|
2009-08-20 09:44:21 +08:00
|
|
|
D->wasDeclaredWithTypename(),
|
|
|
|
D->isParameterPack());
|
2011-03-05 01:52:15 +08:00
|
|
|
Inst->setAccess(AS_public);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-10 03:17:50 +08:00
|
|
|
if (D->hasDefaultArgument())
|
2011-10-08 19:31:46 +08:00
|
|
|
Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
|
2009-08-20 09:44:21 +08:00
|
|
|
|
2011-10-08 19:31:46 +08:00
|
|
|
// Introduce this template parameter's instantiation into the instantiation
|
2009-11-01 01:21:17 +08:00
|
|
|
// scope.
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2009-10-24 07:25:44 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
|
|
|
|
NonTypeTemplateParmDecl *D) {
|
|
|
|
// Substitute into the type of the non-type template parameter.
|
2011-01-20 04:10:05 +08:00
|
|
|
TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten;
|
|
|
|
SmallVector<QualType, 4> ExpandedParameterPackTypes;
|
2011-01-20 04:10:05 +08:00
|
|
|
bool IsExpandedParameterPack = false;
|
2011-10-08 19:31:46 +08:00
|
|
|
TypeSourceInfo *DI;
|
2009-10-24 07:25:44 +08:00
|
|
|
QualType T;
|
|
|
|
bool Invalid = false;
|
2011-01-20 04:10:05 +08:00
|
|
|
|
|
|
|
if (D->isExpandedParameterPack()) {
|
2011-10-08 19:31:46 +08:00
|
|
|
// The non-type template parameter pack is an already-expanded pack
|
2011-01-20 04:10:05 +08:00
|
|
|
// expansion of types. Substitute into each of the expanded types.
|
|
|
|
ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes());
|
|
|
|
ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes());
|
|
|
|
for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
|
|
|
|
TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I),
|
|
|
|
TemplateArgs,
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getLocation(),
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getDeclName());
|
|
|
|
if (!NewDI)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
|
|
|
|
QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(),
|
|
|
|
D->getLocation());
|
|
|
|
if (NewT.isNull())
|
|
|
|
return 0;
|
|
|
|
ExpandedParameterPackTypes.push_back(NewT);
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
IsExpandedParameterPack = true;
|
|
|
|
DI = D->getTypeSourceInfo();
|
|
|
|
T = DI->getType();
|
|
|
|
} else if (isa<PackExpansionTypeLoc>(TL)) {
|
|
|
|
// The non-type template parameter pack's type is a pack expansion of types.
|
|
|
|
// Determine whether we need to expand this parameter pack into separate
|
|
|
|
// types.
|
|
|
|
PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL);
|
|
|
|
TypeLoc Pattern = Expansion.getPatternLoc();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2011-01-20 04:10:05 +08:00
|
|
|
SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
// Determine whether the set of unexpanded parameter packs can and should
|
|
|
|
// be expanded.
|
|
|
|
bool Expand = true;
|
|
|
|
bool RetainExpansion = false;
|
|
|
|
llvm::Optional<unsigned> OrigNumExpansions
|
|
|
|
= Expansion.getTypePtr()->getNumExpansions();
|
|
|
|
llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
|
|
|
|
if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(),
|
|
|
|
Pattern.getSourceRange(),
|
2011-09-22 10:34:54 +08:00
|
|
|
Unexpanded,
|
2011-01-20 04:10:05 +08:00
|
|
|
TemplateArgs,
|
2011-10-08 19:31:46 +08:00
|
|
|
Expand, RetainExpansion,
|
2011-01-20 04:10:05 +08:00
|
|
|
NumExpansions))
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
if (Expand) {
|
|
|
|
for (unsigned I = 0; I != *NumExpansions; ++I) {
|
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
|
|
|
|
TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs,
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getLocation(),
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getDeclName());
|
|
|
|
if (!NewDI)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
ExpandedParameterPackTypesAsWritten.push_back(NewDI);
|
|
|
|
QualType NewT = SemaRef.CheckNonTypeTemplateParameterType(
|
|
|
|
NewDI->getType(),
|
|
|
|
D->getLocation());
|
|
|
|
if (NewT.isNull())
|
|
|
|
return 0;
|
|
|
|
ExpandedParameterPackTypes.push_back(NewT);
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
// Note that we have an expanded parameter pack. The "type" of this
|
|
|
|
// expanded parameter pack is the original expansion type, but callers
|
|
|
|
// will end up using the expanded parameter pack types for type-checking.
|
|
|
|
IsExpandedParameterPack = true;
|
|
|
|
DI = D->getTypeSourceInfo();
|
|
|
|
T = DI->getType();
|
|
|
|
} else {
|
|
|
|
// We cannot fully expand the pack expansion now, so substitute into the
|
|
|
|
// pattern and create a new pack expansion type.
|
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
|
|
|
|
TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs,
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getLocation(),
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getDeclName());
|
|
|
|
if (!NewPattern)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(),
|
|
|
|
NumExpansions);
|
|
|
|
if (!DI)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
T = DI->getType();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Simple case: substitution into a parameter that is not a parameter pack.
|
2011-10-08 19:31:46 +08:00
|
|
|
DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getLocation(), D->getDeclName());
|
|
|
|
if (!DI)
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
// Check that this type is acceptable for a non-type template parameter.
|
2011-10-08 19:31:46 +08:00
|
|
|
T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(),
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getLocation());
|
|
|
|
if (T.isNull()) {
|
|
|
|
T = SemaRef.Context.IntTy;
|
|
|
|
Invalid = true;
|
|
|
|
}
|
2009-10-24 07:25:44 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-20 04:10:05 +08:00
|
|
|
NonTypeTemplateParmDecl *Param;
|
|
|
|
if (IsExpandedParameterPack)
|
2011-10-08 19:31:46 +08:00
|
|
|
Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
|
2011-03-08 16:55:46 +08:00
|
|
|
D->getInnerLocStart(),
|
|
|
|
D->getLocation(),
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getDepth() - TemplateArgs.getNumLevels(),
|
|
|
|
D->getPosition(),
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getIdentifier(), T,
|
|
|
|
DI,
|
|
|
|
ExpandedParameterPackTypes.data(),
|
|
|
|
ExpandedParameterPackTypes.size(),
|
|
|
|
ExpandedParameterPackTypesAsWritten.data());
|
|
|
|
else
|
2011-10-08 19:31:46 +08:00
|
|
|
Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
|
2011-03-08 16:55:46 +08:00
|
|
|
D->getInnerLocStart(),
|
2011-01-20 04:10:05 +08:00
|
|
|
D->getLocation(),
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getDepth() - TemplateArgs.getNumLevels(),
|
|
|
|
D->getPosition(),
|
|
|
|
D->getIdentifier(), T,
|
2011-01-20 04:10:05 +08:00
|
|
|
D->isParameterPack(), DI);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-03-05 01:52:15 +08:00
|
|
|
Param->setAccess(AS_public);
|
2009-10-24 07:25:44 +08:00
|
|
|
if (Invalid)
|
|
|
|
Param->setInvalidDecl();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-06-09 17:26:05 +08:00
|
|
|
Param->setDefaultArgument(D->getDefaultArgument(), false);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
|
|
|
// Introduce this template parameter's instantiation into the instantiation
|
2009-11-01 01:21:17 +08:00
|
|
|
// scope.
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
|
2009-10-24 07:25:44 +08:00
|
|
|
return Param;
|
|
|
|
}
|
|
|
|
|
2009-11-12 00:58:32 +08:00
|
|
|
Decl *
|
|
|
|
TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
|
|
|
|
TemplateTemplateParmDecl *D) {
|
|
|
|
// Instantiate the template parameter list of the template template parameter.
|
|
|
|
TemplateParameterList *TempParams = D->getTemplateParameters();
|
|
|
|
TemplateParameterList *InstParams;
|
|
|
|
{
|
|
|
|
// Perform the actual substitution of template parameters within a new,
|
|
|
|
// local instantiation scope.
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(SemaRef);
|
2009-11-12 00:58:32 +08:00
|
|
|
InstParams = SubstTemplateParams(TempParams);
|
|
|
|
if (!InstParams)
|
|
|
|
return NULL;
|
2011-10-08 19:31:46 +08:00
|
|
|
}
|
|
|
|
|
2009-11-12 00:58:32 +08:00
|
|
|
// Build the template template parameter.
|
|
|
|
TemplateTemplateParmDecl *Param
|
|
|
|
= TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getDepth() - TemplateArgs.getNumLevels(),
|
|
|
|
D->getPosition(), D->isParameterPack(),
|
2011-01-05 23:48:55 +08:00
|
|
|
D->getIdentifier(), InstParams);
|
2010-06-09 17:26:05 +08:00
|
|
|
Param->setDefaultArgument(D->getDefaultArgument(), false);
|
2011-03-05 01:52:15 +08:00
|
|
|
Param->setAccess(AS_public);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
|
|
|
// Introduce this template parameter's instantiation into the instantiation
|
2009-11-12 00:58:32 +08:00
|
|
|
// scope.
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-12 00:58:32 +08:00
|
|
|
return Param;
|
|
|
|
}
|
|
|
|
|
2009-11-17 14:07:40 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
|
2011-02-26 00:33:46 +08:00
|
|
|
// Using directives are never dependent (and never contain any types or
|
|
|
|
// expressions), so they require no explicit instantiation work.
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-17 14:07:40 +08:00
|
|
|
UsingDirectiveDecl *Inst
|
|
|
|
= UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(),
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getNamespaceKeyLocation(),
|
2011-02-26 00:33:46 +08:00
|
|
|
D->getQualifierLoc(),
|
2011-10-08 19:31:46 +08:00
|
|
|
D->getIdentLocation(),
|
|
|
|
D->getNominatedNamespace(),
|
2009-11-17 14:07:40 +08:00
|
|
|
D->getCommonAncestor());
|
|
|
|
Owner->addDecl(Inst);
|
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
|
2010-09-30 01:58:28 +08:00
|
|
|
|
|
|
|
// The nested name specifier may be dependent, for example
|
|
|
|
// template <typename T> struct t {
|
|
|
|
// struct s1 { T f1(); };
|
|
|
|
// struct s2 : s1 { using s1::f1; };
|
|
|
|
// };
|
|
|
|
// template struct t<int>;
|
|
|
|
// Here, in using s1::f1, s1 refers to t<T>::s1;
|
|
|
|
// we need to substitute for t<int>::s1.
|
2011-02-25 23:54:31 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc
|
|
|
|
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
|
|
|
|
TemplateArgs);
|
|
|
|
if (!QualifierLoc)
|
2011-02-25 08:36:19 +08:00
|
|
|
return 0;
|
2010-09-30 01:58:28 +08:00
|
|
|
|
|
|
|
// The name info is non-dependent, so no transformation
|
|
|
|
// is required.
|
2010-08-12 19:46:03 +08:00
|
|
|
DeclarationNameInfo NameInfo = D->getNameInfo();
|
2009-12-05 06:46:56 +08:00
|
|
|
|
2009-12-10 17:41:52 +08:00
|
|
|
// We only need to do redeclaration lookups if we're in a class
|
|
|
|
// scope (in fact, it's not really even possible in non-class
|
|
|
|
// scopes).
|
|
|
|
bool CheckRedeclaration = Owner->isRecord();
|
|
|
|
|
2010-08-12 19:46:03 +08:00
|
|
|
LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
|
|
|
|
Sema::ForRedeclaration);
|
2009-12-10 17:41:52 +08:00
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
|
|
|
|
D->getUsingLocation(),
|
2011-02-25 23:54:31 +08:00
|
|
|
QualifierLoc,
|
2010-08-12 19:46:03 +08:00
|
|
|
NameInfo,
|
2009-12-05 06:46:56 +08:00
|
|
|
D->isTypeName());
|
|
|
|
|
2011-02-25 23:54:31 +08:00
|
|
|
CXXScopeSpec SS;
|
|
|
|
SS.Adopt(QualifierLoc);
|
2009-12-10 17:41:52 +08:00
|
|
|
if (CheckRedeclaration) {
|
|
|
|
Prev.setHideTags(false);
|
|
|
|
SemaRef.LookupQualifiedName(Prev, Owner);
|
|
|
|
|
|
|
|
// Check for invalid redeclarations.
|
|
|
|
if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
|
|
|
|
D->isTypeName(), SS,
|
|
|
|
D->getLocation(), Prev))
|
|
|
|
NewUD->setInvalidDecl();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NewUD->isInvalidDecl() &&
|
|
|
|
SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
|
2009-12-05 06:46:56 +08:00
|
|
|
D->getLocation()))
|
|
|
|
NewUD->setInvalidDecl();
|
2009-12-10 17:41:52 +08:00
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
|
|
|
|
NewUD->setAccess(D->getAccess());
|
|
|
|
Owner->addDecl(NewUD);
|
|
|
|
|
2009-12-10 17:41:52 +08:00
|
|
|
// Don't process the shadow decls for an invalid decl.
|
|
|
|
if (NewUD->isInvalidDecl())
|
|
|
|
return NewUD;
|
|
|
|
|
2012-04-02 09:30:27 +08:00
|
|
|
if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) {
|
|
|
|
if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD))
|
|
|
|
NewUD->setInvalidDecl();
|
|
|
|
return NewUD;
|
|
|
|
}
|
|
|
|
|
2009-12-23 06:26:37 +08:00
|
|
|
bool isFunctionScope = Owner->isFunctionOrMethod();
|
|
|
|
|
2009-12-10 17:41:52 +08:00
|
|
|
// Process the shadow decls.
|
|
|
|
for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
UsingShadowDecl *Shadow = *I;
|
|
|
|
NamedDecl *InstTarget =
|
2011-03-05 03:46:35 +08:00
|
|
|
cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
|
|
|
|
Shadow->getLocation(),
|
|
|
|
Shadow->getTargetDecl(),
|
|
|
|
TemplateArgs));
|
|
|
|
if (!InstTarget)
|
|
|
|
return 0;
|
2009-12-10 17:41:52 +08:00
|
|
|
|
|
|
|
if (CheckRedeclaration &&
|
|
|
|
SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
UsingShadowDecl *InstShadow
|
|
|
|
= SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
|
|
|
|
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
|
2009-12-23 06:26:37 +08:00
|
|
|
|
|
|
|
if (isFunctionScope)
|
|
|
|
SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow);
|
2009-12-10 17:41:52 +08:00
|
|
|
}
|
2009-12-05 06:46:56 +08:00
|
|
|
|
|
|
|
return NewUD;
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
|
2009-12-10 17:41:52 +08:00
|
|
|
// Ignore these; we handle them in bulk when processing the UsingDecl.
|
|
|
|
return 0;
|
2009-12-05 06:46:56 +08:00
|
|
|
}
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
Decl * TemplateDeclInstantiator
|
|
|
|
::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
|
2011-02-25 23:54:31 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc
|
2011-10-08 19:31:46 +08:00
|
|
|
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(),
|
2011-02-25 23:54:31 +08:00
|
|
|
TemplateArgs);
|
|
|
|
if (!QualifierLoc)
|
2009-11-18 10:36:19 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
CXXScopeSpec SS;
|
2011-02-25 23:54:31 +08:00
|
|
|
SS.Adopt(QualifierLoc);
|
2009-11-18 10:36:19 +08:00
|
|
|
|
2010-08-12 19:46:03 +08:00
|
|
|
// Since NameInfo refers to a typename, it cannot be a C++ special name.
|
|
|
|
// Hence, no tranformation is required for it.
|
|
|
|
DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
|
2009-11-18 10:36:19 +08:00
|
|
|
NamedDecl *UD =
|
|
|
|
SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
|
2010-08-12 19:46:03 +08:00
|
|
|
D->getUsingLoc(), SS, NameInfo, 0,
|
2009-11-18 10:36:19 +08:00
|
|
|
/*instantiation*/ true,
|
|
|
|
/*typename*/ true, D->getTypenameLoc());
|
2010-05-20 01:02:24 +08:00
|
|
|
if (UD)
|
2009-12-05 06:46:56 +08:00
|
|
|
SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
return UD;
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl * TemplateDeclInstantiator
|
|
|
|
::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
|
2011-02-25 23:54:31 +08:00
|
|
|
NestedNameSpecifierLoc QualifierLoc
|
|
|
|
= SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs);
|
|
|
|
if (!QualifierLoc)
|
2009-08-28 23:18:15 +08:00
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-08-28 23:18:15 +08:00
|
|
|
CXXScopeSpec SS;
|
2011-02-25 23:54:31 +08:00
|
|
|
SS.Adopt(QualifierLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-12 19:46:03 +08:00
|
|
|
DeclarationNameInfo NameInfo
|
|
|
|
= SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
NamedDecl *UD =
|
2009-11-17 13:59:44 +08:00
|
|
|
SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
|
2010-08-12 19:46:03 +08:00
|
|
|
D->getUsingLoc(), SS, NameInfo, 0,
|
2009-11-18 10:36:19 +08:00
|
|
|
/*instantiation*/ true,
|
|
|
|
/*typename*/ false, SourceLocation());
|
2010-05-20 01:02:24 +08:00
|
|
|
if (UD)
|
2009-12-05 06:46:56 +08:00
|
|
|
SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
|
|
|
|
|
2009-08-30 03:37:28 +08:00
|
|
|
return UD;
|
2009-08-28 23:18:15 +08:00
|
|
|
}
|
|
|
|
|
2011-08-14 11:52:19 +08:00
|
|
|
|
|
|
|
Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
|
|
|
|
ClassScopeFunctionSpecializationDecl *Decl) {
|
|
|
|
CXXMethodDecl *OldFD = Decl->getSpecialization();
|
2012-06-26 01:21:05 +08:00
|
|
|
CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD,
|
|
|
|
0, true));
|
2011-08-14 11:52:19 +08:00
|
|
|
|
|
|
|
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
|
|
|
|
Sema::ForRedeclaration);
|
|
|
|
|
2012-06-26 01:21:05 +08:00
|
|
|
TemplateArgumentListInfo TemplateArgs;
|
|
|
|
TemplateArgumentListInfo* TemplateArgsPtr = 0;
|
|
|
|
if (Decl->hasExplicitTemplateArgs()) {
|
|
|
|
TemplateArgs = Decl->templateArgs();
|
|
|
|
TemplateArgsPtr = &TemplateArgs;
|
|
|
|
}
|
|
|
|
|
2011-08-14 11:52:19 +08:00
|
|
|
SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext);
|
2012-06-26 01:21:05 +08:00
|
|
|
if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, TemplateArgsPtr,
|
|
|
|
Previous)) {
|
2011-08-14 11:52:19 +08:00
|
|
|
NewFD->setInvalidDecl();
|
|
|
|
return NewFD;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Associate the specialization with the pattern.
|
|
|
|
FunctionDecl *Specialization = cast<FunctionDecl>(Previous.getFoundDecl());
|
|
|
|
assert(Specialization && "Class scope Specialization is null");
|
|
|
|
SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD);
|
|
|
|
|
|
|
|
return NewFD;
|
|
|
|
}
|
|
|
|
|
2009-08-26 06:02:44 +08:00
|
|
|
Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
|
2009-08-29 04:31:08 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-05-12 07:53:27 +08:00
|
|
|
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
|
2010-02-17 03:28:15 +08:00
|
|
|
if (D->isInvalidDecl())
|
|
|
|
return 0;
|
|
|
|
|
2009-03-18 05:15:40 +08:00
|
|
|
return Instantiator.Visit(D);
|
|
|
|
}
|
|
|
|
|
2009-08-20 09:44:21 +08:00
|
|
|
/// \brief Instantiates a nested template parameter list in the current
|
|
|
|
/// instantiation context.
|
|
|
|
///
|
|
|
|
/// \param L The parameter list to instantiate
|
|
|
|
///
|
|
|
|
/// \returns NULL if there was an error
|
|
|
|
TemplateParameterList *
|
2009-08-26 06:02:44 +08:00
|
|
|
TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
|
2009-08-20 09:44:21 +08:00
|
|
|
// Get errors for all the parameters before bailing out.
|
|
|
|
bool Invalid = false;
|
|
|
|
|
|
|
|
unsigned N = L->size();
|
2011-07-23 18:55:15 +08:00
|
|
|
typedef SmallVector<NamedDecl *, 8> ParamVector;
|
2009-08-20 09:44:21 +08:00
|
|
|
ParamVector Params;
|
|
|
|
Params.reserve(N);
|
|
|
|
for (TemplateParameterList::iterator PI = L->begin(), PE = L->end();
|
|
|
|
PI != PE; ++PI) {
|
2009-09-16 00:23:51 +08:00
|
|
|
NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI));
|
2009-08-20 09:44:21 +08:00
|
|
|
Params.push_back(D);
|
2009-11-12 03:13:48 +08:00
|
|
|
Invalid = Invalid || !D || D->isInvalidDecl();
|
2009-08-20 09:44:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clean up if we had an error.
|
2010-07-26 02:17:45 +08:00
|
|
|
if (Invalid)
|
2009-08-20 09:44:21 +08:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
TemplateParameterList *InstL
|
|
|
|
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
|
|
|
|
L->getLAngleLoc(), &Params.front(), N,
|
|
|
|
L->getRAngleLoc());
|
|
|
|
return InstL;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-08-20 09:44:21 +08:00
|
|
|
|
2011-10-08 19:31:46 +08:00
|
|
|
/// \brief Instantiate the declaration of a class template partial
|
2009-10-29 08:04:11 +08:00
|
|
|
/// specialization.
|
|
|
|
///
|
|
|
|
/// \param ClassTemplate the (instantiated) class template that is partially
|
|
|
|
// specialized by the instantiation of \p PartialSpec.
|
|
|
|
///
|
2011-10-08 19:31:46 +08:00
|
|
|
/// \param PartialSpec the (uninstantiated) class template partial
|
2009-10-29 08:04:11 +08:00
|
|
|
/// specialization that we are instantiating.
|
|
|
|
///
|
2010-11-11 03:44:59 +08:00
|
|
|
/// \returns The instantiated partial specialization, if successful; otherwise,
|
|
|
|
/// NULL to indicate an error.
|
|
|
|
ClassTemplatePartialSpecializationDecl *
|
2009-10-29 08:04:11 +08:00
|
|
|
TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
|
|
|
|
ClassTemplateDecl *ClassTemplate,
|
|
|
|
ClassTemplatePartialSpecializationDecl *PartialSpec) {
|
2009-11-01 01:21:17 +08:00
|
|
|
// Create a local instantiation scope for this class template partial
|
|
|
|
// specialization, which will contain the instantiations of the template
|
|
|
|
// parameters.
|
2010-08-25 13:32:35 +08:00
|
|
|
LocalInstantiationScope Scope(SemaRef);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Substitute into the template parameters of the class template partial
|
|
|
|
// specialization.
|
|
|
|
TemplateParameterList *TempParams = PartialSpec->getTemplateParameters();
|
|
|
|
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
|
|
|
|
if (!InstParams)
|
2010-11-11 03:44:59 +08:00
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Substitute into the template arguments of the class template partial
|
|
|
|
// specialization.
|
2009-11-23 09:53:49 +08:00
|
|
|
TemplateArgumentListInfo InstTemplateArgs; // no angle locations
|
2011-10-08 19:31:46 +08:00
|
|
|
if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(),
|
|
|
|
PartialSpec->getNumTemplateArgsAsWritten(),
|
2010-12-23 05:19:48 +08:00
|
|
|
InstTemplateArgs, TemplateArgs))
|
|
|
|
return 0;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Check that the template argument list is well-formed for this
|
|
|
|
// class template.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<TemplateArgument, 4> Converted;
|
2011-10-08 19:31:46 +08:00
|
|
|
if (SemaRef.CheckTemplateArgumentList(ClassTemplate,
|
2009-10-29 08:04:11 +08:00
|
|
|
PartialSpec->getLocation(),
|
2011-10-08 19:31:46 +08:00
|
|
|
InstTemplateArgs,
|
2009-10-29 08:04:11 +08:00
|
|
|
false,
|
|
|
|
Converted))
|
2010-11-11 03:44:59 +08:00
|
|
|
return 0;
|
2009-10-29 08:04:11 +08:00
|
|
|
|
|
|
|
// Figure out where to insert this class template partial specialization
|
|
|
|
// in the member template's set of class template partial specializations.
|
|
|
|
void *InsertPos = 0;
|
|
|
|
ClassTemplateSpecializationDecl *PrevDecl
|
2010-11-08 07:05:16 +08:00
|
|
|
= ClassTemplate->findPartialSpecialization(Converted.data(),
|
|
|
|
Converted.size(), InsertPos);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Build the canonical type that describes the converted template
|
|
|
|
// arguments of the class template partial specialization.
|
2011-10-08 19:31:46 +08:00
|
|
|
QualType CanonType
|
2009-10-29 08:04:11 +08:00
|
|
|
= SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate),
|
2010-11-08 07:05:16 +08:00
|
|
|
Converted.data(),
|
|
|
|
Converted.size());
|
2009-10-29 08:04:11 +08:00
|
|
|
|
|
|
|
// Build the fully-sugared type for this class template
|
|
|
|
// specialization as the user wrote in the specialization
|
|
|
|
// itself. This means that we'll pretty-print the type retrieved
|
|
|
|
// from the specialization's declaration the way that the user
|
|
|
|
// actually wrote the specialization, rather than formatting the
|
|
|
|
// name based on the "canonical" representation used to store the
|
|
|
|
// template arguments in the specialization.
|
2010-03-10 11:28:59 +08:00
|
|
|
TypeSourceInfo *WrittenTy
|
|
|
|
= SemaRef.Context.getTemplateSpecializationTypeInfo(
|
|
|
|
TemplateName(ClassTemplate),
|
|
|
|
PartialSpec->getLocation(),
|
2009-11-23 09:53:49 +08:00
|
|
|
InstTemplateArgs,
|
2009-10-29 08:04:11 +08:00
|
|
|
CanonType);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
if (PrevDecl) {
|
|
|
|
// We've already seen a partial specialization with the same template
|
|
|
|
// parameters and template arguments. This can happen, for example, when
|
|
|
|
// substituting the outer template arguments ends up causing two
|
|
|
|
// class template partial specializations of a member class template
|
|
|
|
// to have identical forms, e.g.,
|
|
|
|
//
|
|
|
|
// template<typename T, typename U>
|
|
|
|
// struct Outer {
|
|
|
|
// template<typename X, typename Y> struct Inner;
|
|
|
|
// template<typename Y> struct Inner<T, Y>;
|
|
|
|
// template<typename Y> struct Inner<U, Y>;
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// Outer<int, int> outer; // error: the partial specializations of Inner
|
|
|
|
// // have the same signature.
|
|
|
|
SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared)
|
2010-11-11 03:44:59 +08:00
|
|
|
<< WrittenTy->getType();
|
2009-10-29 08:04:11 +08:00
|
|
|
SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here)
|
|
|
|
<< SemaRef.Context.getTypeDeclType(PrevDecl);
|
2010-11-11 03:44:59 +08:00
|
|
|
return 0;
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Create the class template partial specialization declaration.
|
|
|
|
ClassTemplatePartialSpecializationDecl *InstPartialSpec
|
2011-10-08 19:31:46 +08:00
|
|
|
= ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context,
|
2010-05-06 08:28:52 +08:00
|
|
|
PartialSpec->getTagKind(),
|
2011-10-08 19:31:46 +08:00
|
|
|
Owner,
|
2011-03-09 22:09:51 +08:00
|
|
|
PartialSpec->getLocStart(),
|
|
|
|
PartialSpec->getLocation(),
|
2009-10-29 08:04:11 +08:00
|
|
|
InstParams,
|
2011-10-08 19:31:46 +08:00
|
|
|
ClassTemplate,
|
2010-11-08 07:05:16 +08:00
|
|
|
Converted.data(),
|
|
|
|
Converted.size(),
|
2009-11-23 09:53:49 +08:00
|
|
|
InstTemplateArgs,
|
2010-03-10 11:28:59 +08:00
|
|
|
CanonType,
|
2010-04-30 13:56:50 +08:00
|
|
|
0,
|
2010-07-20 21:59:28 +08:00
|
|
|
ClassTemplate->getNextPartialSpecSequenceNumber());
|
2010-03-15 18:12:16 +08:00
|
|
|
// Substitute the nested name specifier, if any.
|
|
|
|
if (SubstQualifier(PartialSpec, InstPartialSpec))
|
|
|
|
return 0;
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
|
2010-05-20 01:02:24 +08:00
|
|
|
InstPartialSpec->setTypeAsWritten(WrittenTy);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
// Add this partial specialization to the set of class template partial
|
|
|
|
// specializations.
|
2012-03-28 22:34:23 +08:00
|
|
|
ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
|
2010-11-11 03:44:59 +08:00
|
|
|
return InstPartialSpec;
|
2009-10-29 08:04:11 +08:00
|
|
|
}
|
|
|
|
|
2010-03-11 17:03:00 +08:00
|
|
|
TypeSourceInfo*
|
|
|
|
TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVectorImpl<ParmVarDecl *> &Params) {
|
2010-03-11 17:03:00 +08:00
|
|
|
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
|
|
|
|
assert(OldTInfo && "substituting function without type source info");
|
|
|
|
assert(Params.empty() && "parameter vector is non-empty at start");
|
2012-04-16 15:05:22 +08:00
|
|
|
|
|
|
|
CXXRecordDecl *ThisContext = 0;
|
|
|
|
unsigned ThisTypeQuals = 0;
|
|
|
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
|
|
|
ThisContext = Method->getParent();
|
|
|
|
ThisTypeQuals = Method->getTypeQualifiers();
|
|
|
|
}
|
|
|
|
|
2010-04-10 01:38:44 +08:00
|
|
|
TypeSourceInfo *NewTInfo
|
|
|
|
= SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
|
|
|
|
D->getTypeSpecStartLoc(),
|
2012-04-16 15:05:22 +08:00
|
|
|
D->getDeclName(),
|
|
|
|
ThisContext, ThisTypeQuals);
|
2010-03-11 17:03:00 +08:00
|
|
|
if (!NewTInfo)
|
|
|
|
return 0;
|
2009-03-24 08:38:23 +08:00
|
|
|
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
if (NewTInfo != OldTInfo) {
|
|
|
|
// Get parameters from the new type info.
|
2010-12-14 06:27:55 +08:00
|
|
|
TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
|
2010-05-03 23:32:18 +08:00
|
|
|
if (FunctionProtoTypeLoc *OldProtoLoc
|
|
|
|
= dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
|
2010-12-14 06:27:55 +08:00
|
|
|
TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
|
2010-05-03 23:32:18 +08:00
|
|
|
FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
|
|
|
|
assert(NewProtoLoc && "Missing prototype?");
|
2012-07-18 09:29:05 +08:00
|
|
|
unsigned NewIdx = 0;
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-08 00:43:16 +08:00
|
|
|
for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs();
|
|
|
|
OldIdx != NumOldParams; ++OldIdx) {
|
|
|
|
ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);
|
2012-07-18 09:29:05 +08:00
|
|
|
LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope;
|
|
|
|
|
|
|
|
llvm::Optional<unsigned> NumArgumentsInExpansion;
|
|
|
|
if (OldParam->isParameterPack())
|
|
|
|
NumArgumentsInExpansion =
|
|
|
|
SemaRef.getNumArgumentsInExpansion(OldParam->getType(),
|
|
|
|
TemplateArgs);
|
|
|
|
if (!NumArgumentsInExpansion) {
|
2011-10-08 19:31:46 +08:00
|
|
|
// Simple case: normal parameter, or a parameter pack that's
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-08 00:43:16 +08:00
|
|
|
// instantiated to a (still-dependent) parameter pack.
|
|
|
|
ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
|
|
|
|
Params.push_back(NewParam);
|
2012-07-18 09:29:05 +08:00
|
|
|
Scope->InstantiatedLocal(OldParam, NewParam);
|
|
|
|
} else {
|
|
|
|
// Parameter pack expansion: make the instantiation an argument pack.
|
|
|
|
Scope->MakeInstantiatedLocalArgPack(OldParam);
|
|
|
|
for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) {
|
|
|
|
ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
|
|
|
|
Params.push_back(NewParam);
|
|
|
|
Scope->InstantiatedLocalPackArg(OldParam, NewParam);
|
|
|
|
}
|
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary
pack expansions involving function parameter packs. At this point, we
can now correctly compile a simple, variadic print() example:
#include <iostream>
#include <string>
void print() {}
template<typename Head, typename ...Tail>
void print(const Head &head, const Tail &...tail) {
std::cout << head;
print(tail...);
}
int main() {
std::string hello = "Hello";
print(hello, ", world!", " ", 2011, '\n');
}
llvm-svn: 123000
2011-01-08 00:43:16 +08:00
|
|
|
}
|
2010-05-03 23:32:18 +08:00
|
|
|
}
|
2010-05-01 02:55:50 +08:00
|
|
|
}
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
} else {
|
|
|
|
// The function type itself was not dependent and therefore no
|
|
|
|
// substitution occurred. However, we still need to instantiate
|
|
|
|
// the function parameters themselves.
|
2010-12-14 06:27:55 +08:00
|
|
|
TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens();
|
2010-05-03 23:32:18 +08:00
|
|
|
if (FunctionProtoTypeLoc *OldProtoLoc
|
|
|
|
= dyn_cast<FunctionProtoTypeLoc>(&OldTL)) {
|
|
|
|
for (unsigned i = 0, i_end = OldProtoLoc->getNumArgs(); i != i_end; ++i) {
|
|
|
|
ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc->getArg(i));
|
|
|
|
if (!Parm)
|
|
|
|
return 0;
|
|
|
|
Params.push_back(Parm);
|
|
|
|
}
|
Be sure to instantiate the parameters of a function, even when the
function's type is (strictly speaking) non-dependent. This ensures
that, e.g., default function arguments get instantiated properly.
And, since I couldn't resist, collapse the two implementations of
function-parameter instantiation into calls to a single, new function
(Sema::SubstParmVarDecl), since the two had nearly identical code (and
each had bugs the other didn't!). More importantly, factored out the
semantic analysis of a parameter declaration into
Sema::CheckParameter, which is called both by
Sema::ActOnParamDeclarator (when parameters are parsed) and when a
parameter is instantiated. Previously, we were missing some
Objective-C and address-space checks on instantiated function
parameters.
Fixes PR6733.
llvm-svn: 101029
2010-04-12 15:48:19 +08:00
|
|
|
}
|
|
|
|
}
|
2010-03-11 17:03:00 +08:00
|
|
|
return NewTInfo;
|
2009-03-24 08:38:23 +08:00
|
|
|
}
|
|
|
|
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
/// Introduce the instantiated function parameters into the local
|
|
|
|
/// instantiation scope, and set the parameter names to those used
|
|
|
|
/// in the template.
|
|
|
|
static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
|
|
|
|
const FunctionDecl *PatternDecl,
|
|
|
|
LocalInstantiationScope &Scope,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
|
|
|
unsigned FParamIdx = 0;
|
|
|
|
for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
|
|
|
|
const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
|
|
|
|
if (!PatternParam->isParameterPack()) {
|
|
|
|
// Simple case: not a parameter pack.
|
|
|
|
assert(FParamIdx < Function->getNumParams());
|
|
|
|
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
|
|
|
|
FunctionParam->setDeclName(PatternParam->getDeclName());
|
|
|
|
Scope.InstantiatedLocal(PatternParam, FunctionParam);
|
|
|
|
++FParamIdx;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Expand the parameter pack.
|
|
|
|
Scope.MakeInstantiatedLocalArgPack(PatternParam);
|
2012-07-18 09:29:05 +08:00
|
|
|
llvm::Optional<unsigned> NumArgumentsInExpansion
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
= S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
|
2012-07-18 09:29:05 +08:00
|
|
|
assert(NumArgumentsInExpansion &&
|
|
|
|
"should only be called when all template arguments are known");
|
|
|
|
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
|
|
|
|
FunctionParam->setDeclName(PatternParam->getDeclName());
|
|
|
|
Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
|
|
|
|
++FParamIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
|
|
|
|
const FunctionProtoType *Proto,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2012-04-19 08:08:28 +08:00
|
|
|
assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
|
|
|
|
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
// C++11 [expr.prim.general]p3:
|
|
|
|
// If a declaration declares a member function or member function
|
|
|
|
// template of a class X, the expression this is a prvalue of type
|
|
|
|
// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
|
|
|
|
// and the end of the function-definition, member-declarator, or
|
|
|
|
// declarator.
|
|
|
|
CXXRecordDecl *ThisContext = 0;
|
|
|
|
unsigned ThisTypeQuals = 0;
|
|
|
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
|
|
|
|
ThisContext = Method->getParent();
|
|
|
|
ThisTypeQuals = Method->getTypeQualifiers();
|
|
|
|
}
|
|
|
|
Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
|
|
|
|
SemaRef.getLangOpts().CPlusPlus0x);
|
|
|
|
|
|
|
|
// The function has an exception specification or a "noreturn"
|
|
|
|
// attribute. Substitute into each of the exception types.
|
|
|
|
SmallVector<QualType, 4> Exceptions;
|
|
|
|
for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
|
|
|
|
// FIXME: Poor location information!
|
|
|
|
if (const PackExpansionType *PackExpansion
|
|
|
|
= Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
|
|
|
|
// We have a pack expansion. Instantiate it.
|
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
|
|
|
SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
|
|
|
|
Unexpanded);
|
|
|
|
assert(!Unexpanded.empty() &&
|
|
|
|
"Pack expansion without parameter packs?");
|
|
|
|
|
|
|
|
bool Expand = false;
|
|
|
|
bool RetainExpansion = false;
|
|
|
|
llvm::Optional<unsigned> NumExpansions
|
|
|
|
= PackExpansion->getNumExpansions();
|
|
|
|
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
|
|
|
|
SourceRange(),
|
|
|
|
Unexpanded,
|
|
|
|
TemplateArgs,
|
|
|
|
Expand,
|
|
|
|
RetainExpansion,
|
|
|
|
NumExpansions))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (!Expand) {
|
|
|
|
// We can't expand this pack expansion into separate arguments yet;
|
|
|
|
// just substitute into the pattern and create a new pack expansion
|
|
|
|
// type.
|
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
|
|
|
|
QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
|
|
|
|
TemplateArgs,
|
|
|
|
New->getLocation(), New->getDeclName());
|
|
|
|
if (T.isNull())
|
|
|
|
break;
|
|
|
|
|
|
|
|
T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
|
|
|
|
Exceptions.push_back(T);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Substitute into the pack expansion pattern for each template
|
|
|
|
bool Invalid = false;
|
|
|
|
for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
|
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
|
|
|
|
|
|
|
|
QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
|
|
|
|
TemplateArgs,
|
|
|
|
New->getLocation(), New->getDeclName());
|
|
|
|
if (T.isNull()) {
|
|
|
|
Invalid = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Exceptions.push_back(T);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Invalid)
|
|
|
|
break;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType T
|
|
|
|
= SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
|
|
|
|
New->getLocation(), New->getDeclName());
|
|
|
|
if (T.isNull() ||
|
|
|
|
SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Exceptions.push_back(T);
|
|
|
|
}
|
|
|
|
Expr *NoexceptExpr = 0;
|
|
|
|
if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(SemaRef,
|
|
|
|
Sema::ConstantEvaluated);
|
|
|
|
ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
|
|
|
|
if (E.isUsable())
|
|
|
|
E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
|
|
|
|
|
|
|
|
if (E.isUsable()) {
|
|
|
|
NoexceptExpr = E.take();
|
|
|
|
if (!NoexceptExpr->isTypeDependent() &&
|
|
|
|
!NoexceptExpr->isValueDependent())
|
2012-05-05 06:38:52 +08:00
|
|
|
NoexceptExpr
|
|
|
|
= SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
|
|
|
|
0, diag::err_noexcept_needs_constant_expression,
|
|
|
|
/*AllowFold*/ false).take();
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rebuild the function type
|
|
|
|
const FunctionProtoType *NewProto
|
|
|
|
= New->getType()->getAs<FunctionProtoType>();
|
|
|
|
assert(NewProto && "Template instantiation without function prototype?");
|
|
|
|
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
|
|
|
|
EPI.ExceptionSpecType = Proto->getExceptionSpecType();
|
|
|
|
EPI.NumExceptions = Exceptions.size();
|
|
|
|
EPI.Exceptions = Exceptions.data();
|
|
|
|
EPI.NoexceptExpr = NoexceptExpr;
|
|
|
|
|
|
|
|
New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
|
|
|
|
NewProto->arg_type_begin(),
|
|
|
|
NewProto->getNumArgs(),
|
|
|
|
EPI));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
|
|
|
|
FunctionDecl *Decl) {
|
2012-04-19 08:08:28 +08:00
|
|
|
const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();
|
|
|
|
if (Proto->getExceptionSpecType() != EST_Uninstantiated)
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
|
|
|
|
InstantiatingTemplate::ExceptionSpecification());
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
if (Inst) {
|
|
|
|
// We hit the instantiation depth limit. Clear the exception specification
|
|
|
|
// so that our callers don't have to cope with EST_Uninstantiated.
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
|
|
|
EPI.ExceptionSpecType = EST_None;
|
|
|
|
Decl->setType(Context.getFunctionType(Proto->getResultType(),
|
|
|
|
Proto->arg_type_begin(),
|
|
|
|
Proto->getNumArgs(),
|
|
|
|
EPI));
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
return;
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
}
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
|
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
|
|
|
Sema::ContextRAII savedContext(*this, Decl);
|
|
|
|
LocalInstantiationScope Scope(*this);
|
|
|
|
|
|
|
|
MultiLevelTemplateArgumentList TemplateArgs =
|
|
|
|
getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
|
|
|
|
|
2012-04-19 08:08:28 +08:00
|
|
|
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
|
|
|
|
addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
|
2012-04-19 08:08:28 +08:00
|
|
|
::InstantiateExceptionSpec(*this, Decl,
|
|
|
|
Template->getType()->castAs<FunctionProtoType>(),
|
|
|
|
TemplateArgs);
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// \brief Initializes the common fields of an instantiation function
|
2009-06-26 06:08:12 +08:00
|
|
|
/// declaration (New) from the corresponding fields of its template (Tmpl).
|
|
|
|
///
|
|
|
|
/// \returns true if there was an error
|
2009-09-09 23:08:12 +08:00
|
|
|
bool
|
|
|
|
TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
|
2009-06-26 06:08:12 +08:00
|
|
|
FunctionDecl *Tmpl) {
|
2012-07-17 02:50:45 +08:00
|
|
|
if (Tmpl->isDeleted())
|
2011-05-07 04:44:56 +08:00
|
|
|
New->setDeletedAsWritten();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-02 06:01:06 +08:00
|
|
|
// If we are performing substituting explicitly-specified template arguments
|
|
|
|
// or deduced template arguments into a function template and we reach this
|
|
|
|
// point, we are now past the point where SFINAE applies and have committed
|
2009-09-09 23:08:12 +08:00
|
|
|
// to keeping the new function template specialization. We therefore
|
|
|
|
// convert the active template instantiation for the function template
|
2009-07-02 06:01:06 +08:00
|
|
|
// into a template instantiation for this specific function template
|
|
|
|
// specialization, which is not a SFINAE context, so that we diagnose any
|
|
|
|
// further errors in the declaration itself.
|
|
|
|
typedef Sema::ActiveTemplateInstantiation ActiveInstType;
|
|
|
|
ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
|
|
|
|
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
|
|
|
|
ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
|
2009-09-09 23:08:12 +08:00
|
|
|
if (FunctionTemplateDecl *FunTmpl
|
2009-07-02 06:01:06 +08:00
|
|
|
= dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
|
2009-07-02 06:01:06 +08:00
|
|
|
"Deduction from the wrong function template?");
|
2009-07-17 06:10:11 +08:00
|
|
|
(void) FunTmpl;
|
2009-07-02 06:01:06 +08:00
|
|
|
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
|
|
|
|
ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-09 01:45:32 +08:00
|
|
|
const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>();
|
|
|
|
assert(Proto && "Function template without prototype?");
|
|
|
|
|
2011-03-12 19:50:43 +08:00
|
|
|
if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
|
2010-12-14 16:05:40 +08:00
|
|
|
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
|
|
|
|
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
// DR1330: In C++11, defer instantiation of a non-trivial
|
|
|
|
// exception specification.
|
|
|
|
if (SemaRef.getLangOpts().CPlusPlus0x &&
|
|
|
|
EPI.ExceptionSpecType != EST_None &&
|
|
|
|
EPI.ExceptionSpecType != EST_DynamicNone &&
|
|
|
|
EPI.ExceptionSpecType != EST_BasicNoexcept) {
|
2012-04-19 08:08:28 +08:00
|
|
|
FunctionDecl *ExceptionSpecTemplate = Tmpl;
|
|
|
|
if (EPI.ExceptionSpecType == EST_Uninstantiated)
|
|
|
|
ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
assert(EPI.ExceptionSpecType != EST_Unevaluated &&
|
|
|
|
"instantiating implicitly-declared special member");
|
2012-04-19 08:08:28 +08:00
|
|
|
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
// Mark the function has having an uninstantiated exception specification.
|
|
|
|
const FunctionProtoType *NewProto
|
|
|
|
= New->getType()->getAs<FunctionProtoType>();
|
|
|
|
assert(NewProto && "Template instantiation without function prototype?");
|
|
|
|
EPI = NewProto->getExtProtoInfo();
|
|
|
|
EPI.ExceptionSpecType = EST_Uninstantiated;
|
|
|
|
EPI.ExceptionSpecDecl = New;
|
2012-04-19 08:08:28 +08:00
|
|
|
EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
|
|
|
|
NewProto->arg_type_begin(),
|
|
|
|
NewProto->getNumArgs(),
|
|
|
|
EPI));
|
|
|
|
} else {
|
|
|
|
::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
|
|
|
|
}
|
2009-12-09 01:45:32 +08:00
|
|
|
}
|
|
|
|
|
2011-07-06 23:46:09 +08:00
|
|
|
// Get the definition. Leaves the variable unchanged if undefined.
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
const FunctionDecl *Definition = Tmpl;
|
2011-07-06 23:46:09 +08:00
|
|
|
Tmpl->isDefined(Definition);
|
|
|
|
|
2012-01-21 06:50:54 +08:00
|
|
|
SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
|
|
|
|
LateAttrs, StartingScope);
|
2010-06-16 01:05:35 +08:00
|
|
|
|
2009-06-26 06:08:12 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-03-24 08:38:23 +08:00
|
|
|
/// \brief Initializes common fields of an instantiated method
|
|
|
|
/// declaration (New) from the corresponding fields of its template
|
|
|
|
/// (Tmpl).
|
|
|
|
///
|
|
|
|
/// \returns true if there was an error
|
2009-09-09 23:08:12 +08:00
|
|
|
bool
|
|
|
|
TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
|
2009-03-24 08:38:23 +08:00
|
|
|
CXXMethodDecl *Tmpl) {
|
2009-06-26 06:08:12 +08:00
|
|
|
if (InitFunctionInstantiation(New, Tmpl))
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-24 08:38:23 +08:00
|
|
|
New->setAccess(Tmpl->getAccess());
|
2009-12-04 02:44:40 +08:00
|
|
|
if (Tmpl->isVirtualAsWritten())
|
2010-09-29 04:50:54 +08:00
|
|
|
New->setVirtualAsWritten(true);
|
2009-03-24 08:38:23 +08:00
|
|
|
|
|
|
|
// FIXME: attributes
|
|
|
|
// FIXME: New needs a pointer to Tmpl
|
|
|
|
return false;
|
|
|
|
}
|
2009-05-14 04:28:22 +08:00
|
|
|
|
|
|
|
/// \brief Instantiate the definition of the given function from its
|
|
|
|
/// template.
|
|
|
|
///
|
2009-07-01 01:20:14 +08:00
|
|
|
/// \param PointOfInstantiation the point at which the instantiation was
|
|
|
|
/// required. Note that this is not precisely a "point of instantiation"
|
|
|
|
/// for the function, but it's close.
|
|
|
|
///
|
2009-05-14 04:28:22 +08:00
|
|
|
/// \param Function the already-instantiated declaration of a
|
2009-07-01 01:20:14 +08:00
|
|
|
/// function template specialization or member function of a class template
|
|
|
|
/// specialization.
|
|
|
|
///
|
|
|
|
/// \param Recursive if true, recursively instantiates any functions that
|
|
|
|
/// are required by this instantiation.
|
2009-10-15 22:05:49 +08:00
|
|
|
///
|
|
|
|
/// \param DefinitionRequired if true, then we are performing an explicit
|
|
|
|
/// instantiation where the body of the function is required. Complain if
|
|
|
|
/// there is no such body.
|
2009-05-19 01:01:57 +08:00
|
|
|
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
2009-07-01 01:20:14 +08:00
|
|
|
FunctionDecl *Function,
|
2009-10-15 22:05:49 +08:00
|
|
|
bool Recursive,
|
|
|
|
bool DefinitionRequired) {
|
2011-05-07 04:44:56 +08:00
|
|
|
if (Function->isInvalidDecl() || Function->isDefined())
|
2009-05-15 07:26:13 +08:00
|
|
|
return;
|
|
|
|
|
2011-08-14 11:52:19 +08:00
|
|
|
// Never instantiate an explicit specialization except if it is a class scope
|
|
|
|
// explicit specialization.
|
|
|
|
if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
|
|
|
|
!Function->getClassScopeSpecializationPattern())
|
2009-10-08 15:24:58 +08:00
|
|
|
return;
|
2010-05-18 01:34:56 +08:00
|
|
|
|
2009-05-15 05:06:31 +08:00
|
|
|
// Find the function body that we'll be substituting.
|
2009-10-28 04:53:28 +08:00
|
|
|
const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern();
|
2011-05-28 04:00:14 +08:00
|
|
|
assert(PatternDecl && "instantiating a non-template");
|
|
|
|
|
|
|
|
Stmt *Pattern = PatternDecl->getBody(PatternDecl);
|
|
|
|
assert(PatternDecl && "template definition is not a template");
|
|
|
|
if (!Pattern) {
|
|
|
|
// Try to find a defaulted definition
|
|
|
|
PatternDecl->isDefined(PatternDecl);
|
2011-05-26 06:02:25 +08:00
|
|
|
}
|
2011-05-28 04:00:14 +08:00
|
|
|
assert(PatternDecl && "template definition is not a template");
|
2009-05-15 05:06:31 +08:00
|
|
|
|
2011-04-23 06:18:13 +08:00
|
|
|
// Postpone late parsed template instantiations.
|
2011-05-28 04:00:14 +08:00
|
|
|
if (PatternDecl->isLateTemplateParsed() &&
|
2011-05-12 11:51:24 +08:00
|
|
|
!LateTemplateParser) {
|
2011-04-23 06:18:13 +08:00
|
|
|
PendingInstantiations.push_back(
|
|
|
|
std::make_pair(Function, PointOfInstantiation));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call the LateTemplateParser callback if there a need to late parse
|
2011-10-08 19:31:46 +08:00
|
|
|
// a templated function definition.
|
2011-05-28 04:00:14 +08:00
|
|
|
if (!Pattern && PatternDecl->isLateTemplateParsed() &&
|
2011-04-23 06:18:13 +08:00
|
|
|
LateTemplateParser) {
|
2011-04-23 19:52:20 +08:00
|
|
|
LateTemplateParser(OpaqueParser, PatternDecl);
|
2011-04-23 06:18:13 +08:00
|
|
|
Pattern = PatternDecl->getBody(PatternDecl);
|
|
|
|
}
|
|
|
|
|
2011-05-28 04:00:14 +08:00
|
|
|
if (!Pattern && !PatternDecl->isDefaulted()) {
|
2009-10-15 22:05:49 +08:00
|
|
|
if (DefinitionRequired) {
|
|
|
|
if (Function->getPrimaryTemplate())
|
2011-10-08 19:31:46 +08:00
|
|
|
Diag(PointOfInstantiation,
|
2009-10-15 22:05:49 +08:00
|
|
|
diag::err_explicit_instantiation_undefined_func_template)
|
|
|
|
<< Function->getPrimaryTemplate();
|
|
|
|
else
|
2011-10-08 19:31:46 +08:00
|
|
|
Diag(PointOfInstantiation,
|
2009-10-15 22:05:49 +08:00
|
|
|
diag::err_explicit_instantiation_undefined_member)
|
|
|
|
<< 1 << Function->getDeclName() << Function->getDeclContext();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-15 22:05:49 +08:00
|
|
|
if (PatternDecl)
|
2011-10-08 19:31:46 +08:00
|
|
|
Diag(PatternDecl->getLocation(),
|
2009-10-15 22:05:49 +08:00
|
|
|
diag::note_explicit_instantiation_here);
|
2010-05-18 01:57:54 +08:00
|
|
|
Function->setInvalidDecl();
|
2010-08-25 16:27:02 +08:00
|
|
|
} else if (Function->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitInstantiationDefinition) {
|
2010-08-25 16:44:16 +08:00
|
|
|
PendingInstantiations.push_back(
|
2010-08-25 16:27:02 +08:00
|
|
|
std::make_pair(Function, PointOfInstantiation));
|
2009-10-15 22:05:49 +08:00
|
|
|
}
|
2010-08-25 16:27:02 +08:00
|
|
|
|
2009-05-15 05:06:31 +08:00
|
|
|
return;
|
2009-10-15 22:05:49 +08:00
|
|
|
}
|
2009-05-15 05:06:31 +08:00
|
|
|
|
2009-09-05 06:48:11 +08:00
|
|
|
// C++0x [temp.explicit]p9:
|
|
|
|
// Except for inline functions, other explicit instantiation declarations
|
2009-09-09 23:08:12 +08:00
|
|
|
// have the effect of suppressing the implicit instantiation of the entity
|
2009-09-05 06:48:11 +08:00
|
|
|
// to which they refer.
|
2009-09-09 23:08:12 +08:00
|
|
|
if (Function->getTemplateSpecializationKind()
|
2009-09-05 06:48:11 +08:00
|
|
|
== TSK_ExplicitInstantiationDeclaration &&
|
2009-10-28 05:11:48 +08:00
|
|
|
!PatternDecl->isInlined())
|
2009-09-05 06:48:11 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-19 01:01:57 +08:00
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
|
|
|
|
if (Inst)
|
2011-10-08 19:31:46 +08:00
|
|
|
return;
|
|
|
|
|
2011-11-18 16:08:52 +08:00
|
|
|
// Copy the inner loc start from the pattern.
|
|
|
|
Function->setInnerLocStart(PatternDecl->getInnerLocStart());
|
|
|
|
|
2009-07-01 01:20:14 +08:00
|
|
|
// If we're performing recursive template instantiation, create our own
|
|
|
|
// queue of pending implicit instantiations that we will instantiate later,
|
|
|
|
// while we're still within our own instantiation context.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<VTableUse, 16> SavedVTableUses;
|
2010-08-25 16:44:16 +08:00
|
|
|
std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
|
2010-11-25 08:35:20 +08:00
|
|
|
if (Recursive) {
|
|
|
|
VTableUses.swap(SavedVTableUses);
|
2010-08-25 16:44:16 +08:00
|
|
|
PendingInstantiations.swap(SavedPendingInstantiations);
|
2010-11-25 08:35:20 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-10-08 19:31:46 +08:00
|
|
|
EnterExpressionEvaluationContext EvalContext(*this,
|
2010-08-27 07:41:50 +08:00
|
|
|
Sema::PotentiallyEvaluated);
|
2010-08-21 17:40:31 +08:00
|
|
|
ActOnStartOfFunctionDef(0, Function);
|
2009-05-16 01:59:04 +08:00
|
|
|
|
2009-05-15 07:26:13 +08:00
|
|
|
// Introduce a new scope where local variable instantiations will be
|
2010-01-17 06:29:39 +08:00
|
|
|
// recorded, unless we're actually a member function within a local
|
|
|
|
// class, in which case we need to merge our results with the parent
|
|
|
|
// scope (of the enclosing function).
|
|
|
|
bool MergeWithParentScope = false;
|
|
|
|
if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()))
|
|
|
|
MergeWithParentScope = Rec->isLocalClass();
|
|
|
|
|
|
|
|
LocalInstantiationScope Scope(*this, MergeWithParentScope);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-13 14:56:52 +08:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
|
|
|
Sema::ContextRAII savedContext(*this, Function);
|
|
|
|
|
|
|
|
MultiLevelTemplateArgumentList TemplateArgs =
|
|
|
|
getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
|
|
|
|
|
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function
type with this exception specification carries a pointer to a FunctionDecl, and
the exception specification for that FunctionDecl is instantiated (if needed)
and used in the place of the function type's exception specification.
When a function template declaration with a non-trivial exception specification
is instantiated, the specialization's exception specification is set to this
new 'uninstantiated' kind rather than being instantiated immediately.
Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs
on-demand. Also, any odr-use of a function triggers the instantiation of its
exception specification (the exception specification could be needed by IRGen).
In passing, fix two places where a DeclRefExpr was created but the corresponding
function was not actually marked odr-used. We used to get away with this, but
don't any more.
Also fix a bug where instantiating an exception specification which refers to
function parameters resulted in a crash. We still have the same bug in default
arguments, which I'll be looking into next.
This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to
parse (and, in very limited testing, support) all of libstdc++4.7's standard
headers.
llvm-svn: 154886
2012-04-17 08:58:00 +08:00
|
|
|
addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
|
|
|
|
TemplateArgs);
|
2009-05-15 07:26:13 +08:00
|
|
|
|
2011-05-24 07:14:04 +08:00
|
|
|
if (PatternDecl->isDefaulted()) {
|
|
|
|
ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-05-24 07:14:04 +08:00
|
|
|
SetDeclDefaulted(Function, PatternDecl->getLocation());
|
|
|
|
} else {
|
|
|
|
// If this is a constructor, instantiate the member initializers.
|
|
|
|
if (const CXXConstructorDecl *Ctor =
|
|
|
|
dyn_cast<CXXConstructorDecl>(PatternDecl)) {
|
|
|
|
InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor,
|
|
|
|
TemplateArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the function body.
|
|
|
|
StmtResult Body = SubstStmt(Pattern, TemplateArgs);
|
|
|
|
|
|
|
|
if (Body.isInvalid())
|
|
|
|
Function->setInvalidDecl();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-05-24 07:14:04 +08:00
|
|
|
ActOnFinishFunctionBody(Function, Body.get(),
|
|
|
|
/*IsInstantiation=*/true);
|
|
|
|
}
|
2009-05-15 08:01:03 +08:00
|
|
|
|
2010-03-24 13:22:00 +08:00
|
|
|
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
|
|
|
|
|
2011-02-14 15:13:47 +08:00
|
|
|
savedContext.pop();
|
2009-05-27 04:50:29 +08:00
|
|
|
|
|
|
|
DeclGroupRef DG(Function);
|
|
|
|
Consumer.HandleTopLevelDecl(DG);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-01-17 06:29:39 +08:00
|
|
|
// This class may have local implicit instantiations that need to be
|
|
|
|
// instantiation within this scope.
|
2010-08-25 16:44:16 +08:00
|
|
|
PerformPendingInstantiations(/*LocalOnly=*/true);
|
2010-01-17 06:29:39 +08:00
|
|
|
Scope.Exit();
|
|
|
|
|
2009-07-01 01:20:14 +08:00
|
|
|
if (Recursive) {
|
2010-11-25 08:35:20 +08:00
|
|
|
// Define any pending vtables.
|
|
|
|
DefineUsedVTables();
|
|
|
|
|
2009-07-01 01:20:14 +08:00
|
|
|
// Instantiate any pending implicit instantiations found during the
|
2009-09-09 23:08:12 +08:00
|
|
|
// instantiation of this template.
|
2010-08-25 16:44:16 +08:00
|
|
|
PerformPendingInstantiations();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-11-25 08:35:20 +08:00
|
|
|
// Restore the set of pending vtables.
|
2011-05-31 15:58:42 +08:00
|
|
|
assert(VTableUses.empty() &&
|
|
|
|
"VTableUses should be empty before it is discarded.");
|
2010-11-25 08:35:20 +08:00
|
|
|
VTableUses.swap(SavedVTableUses);
|
|
|
|
|
2009-07-01 01:20:14 +08:00
|
|
|
// Restore the set of pending implicit instantiations.
|
2011-05-31 15:58:42 +08:00
|
|
|
assert(PendingInstantiations.empty() &&
|
|
|
|
"PendingInstantiations should be empty before it is discarded.");
|
2010-08-25 16:44:16 +08:00
|
|
|
PendingInstantiations.swap(SavedPendingInstantiations);
|
2009-07-01 01:20:14 +08:00
|
|
|
}
|
2009-05-14 04:28:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Instantiate the definition of the given variable from its
|
|
|
|
/// template.
|
|
|
|
///
|
2009-07-25 04:34:43 +08:00
|
|
|
/// \param PointOfInstantiation the point at which the instantiation was
|
|
|
|
/// required. Note that this is not precisely a "point of instantiation"
|
|
|
|
/// for the function, but it's close.
|
|
|
|
///
|
|
|
|
/// \param Var the already-instantiated declaration of a static member
|
|
|
|
/// variable of a class template specialization.
|
|
|
|
///
|
|
|
|
/// \param Recursive if true, recursively instantiates any functions that
|
|
|
|
/// are required by this instantiation.
|
2009-10-15 22:05:49 +08:00
|
|
|
///
|
|
|
|
/// \param DefinitionRequired if true, then we are performing an explicit
|
|
|
|
/// instantiation where an out-of-line definition of the member variable
|
|
|
|
/// is required. Complain if there is no such definition.
|
2009-07-25 04:34:43 +08:00
|
|
|
void Sema::InstantiateStaticDataMemberDefinition(
|
|
|
|
SourceLocation PointOfInstantiation,
|
|
|
|
VarDecl *Var,
|
2009-10-15 22:05:49 +08:00
|
|
|
bool Recursive,
|
|
|
|
bool DefinitionRequired) {
|
2009-07-25 04:34:43 +08:00
|
|
|
if (Var->isInvalidDecl())
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// Find the out-of-line definition of this static data member.
|
|
|
|
VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
|
|
|
|
assert(Def && "This data member was not instantiated from a template?");
|
2011-10-08 19:31:46 +08:00
|
|
|
assert(Def->isStaticDataMember() && "Not a static data member?");
|
2009-10-28 02:42:08 +08:00
|
|
|
Def = Def->getOutOfLineDefinition();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-10-28 02:42:08 +08:00
|
|
|
if (!Def) {
|
2009-07-25 04:34:43 +08:00
|
|
|
// We did not find an out-of-line definition of this static data member,
|
|
|
|
// so we won't perform any instantiation. Rather, we rely on the user to
|
2009-09-09 23:08:12 +08:00
|
|
|
// instantiate this definition (or provide a specialization for it) in
|
|
|
|
// another translation unit.
|
2009-10-15 22:05:49 +08:00
|
|
|
if (DefinitionRequired) {
|
2009-10-28 02:42:08 +08:00
|
|
|
Def = Var->getInstantiatedFromStaticDataMember();
|
2011-10-08 19:31:46 +08:00
|
|
|
Diag(PointOfInstantiation,
|
2009-10-15 22:05:49 +08:00
|
|
|
diag::err_explicit_instantiation_undefined_member)
|
|
|
|
<< 2 << Var->getDeclName() << Var->getDeclContext();
|
|
|
|
Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
|
2010-08-25 16:27:02 +08:00
|
|
|
} else if (Var->getTemplateSpecializationKind()
|
|
|
|
== TSK_ExplicitInstantiationDefinition) {
|
2010-08-25 16:44:16 +08:00
|
|
|
PendingInstantiations.push_back(
|
2010-08-25 16:27:02 +08:00
|
|
|
std::make_pair(Var, PointOfInstantiation));
|
|
|
|
}
|
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-05 18:54:55 +08:00
|
|
|
TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
|
|
|
|
|
2009-10-08 15:24:58 +08:00
|
|
|
// Never instantiate an explicit specialization.
|
2012-03-05 18:54:55 +08:00
|
|
|
if (TSK == TSK_ExplicitSpecialization)
|
2009-10-08 15:24:58 +08:00
|
|
|
return;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-08 15:24:58 +08:00
|
|
|
// C++0x [temp.explicit]p9:
|
|
|
|
// Except for inline functions, other explicit instantiation declarations
|
|
|
|
// have the effect of suppressing the implicit instantiation of the entity
|
|
|
|
// to which they refer.
|
2012-03-05 18:54:55 +08:00
|
|
|
if (TSK == TSK_ExplicitInstantiationDeclaration)
|
2009-10-08 15:24:58 +08:00
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-03-08 23:51:03 +08:00
|
|
|
Consumer.HandleCXXStaticMemberVarInstantiation(Var);
|
|
|
|
|
2011-06-03 11:35:07 +08:00
|
|
|
// If we already have a definition, we're done.
|
2012-04-04 10:38:36 +08:00
|
|
|
if (VarDecl *Def = Var->getDefinition()) {
|
|
|
|
// We may be explicitly instantiating something we've already implicitly
|
|
|
|
// instantiated.
|
|
|
|
Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(),
|
|
|
|
PointOfInstantiation);
|
2011-06-03 11:35:07 +08:00
|
|
|
return;
|
2012-04-04 10:38:36 +08:00
|
|
|
}
|
2011-06-03 11:35:07 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
|
|
|
|
if (Inst)
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// If we're performing recursive template instantiation, create our own
|
|
|
|
// queue of pending implicit instantiations that we will instantiate later,
|
|
|
|
// while we're still within our own instantiation context.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<VTableUse, 16> SavedVTableUses;
|
2010-08-25 16:44:16 +08:00
|
|
|
std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
|
2011-05-31 15:58:42 +08:00
|
|
|
if (Recursive) {
|
|
|
|
VTableUses.swap(SavedVTableUses);
|
2010-08-25 16:44:16 +08:00
|
|
|
PendingInstantiations.swap(SavedPendingInstantiations);
|
2011-05-31 15:58:42 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// Enter the scope of this instantiation. We don't use
|
|
|
|
// PushDeclContext because we don't have a scope.
|
2011-02-15 04:37:25 +08:00
|
|
|
ContextRAII previousContext(*this, Var->getDeclContext());
|
2012-02-17 05:36:18 +08:00
|
|
|
LocalInstantiationScope Local(*this);
|
|
|
|
|
2009-10-15 05:29:40 +08:00
|
|
|
VarDecl *OldVar = Var;
|
2009-08-26 06:02:44 +08:00
|
|
|
Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
|
2010-11-29 06:53:37 +08:00
|
|
|
getTemplateInstantiationArgs(Var)));
|
2011-02-15 04:37:25 +08:00
|
|
|
|
|
|
|
previousContext.pop();
|
2009-07-25 04:34:43 +08:00
|
|
|
|
|
|
|
if (Var) {
|
2009-10-16 02:07:02 +08:00
|
|
|
MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo();
|
|
|
|
assert(MSInfo && "Missing member specialization information?");
|
|
|
|
Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(),
|
|
|
|
MSInfo->getPointOfInstantiation());
|
2009-07-25 04:34:43 +08:00
|
|
|
DeclGroupRef DG(Var);
|
|
|
|
Consumer.HandleTopLevelDecl(DG);
|
|
|
|
}
|
2012-02-17 05:36:18 +08:00
|
|
|
Local.Exit();
|
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
if (Recursive) {
|
2011-05-31 15:58:42 +08:00
|
|
|
// Define any newly required vtables.
|
|
|
|
DefineUsedVTables();
|
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// Instantiate any pending implicit instantiations found during the
|
2009-09-09 23:08:12 +08:00
|
|
|
// instantiation of this template.
|
2010-08-25 16:44:16 +08:00
|
|
|
PerformPendingInstantiations();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-05-31 15:58:42 +08:00
|
|
|
// Restore the set of pending vtables.
|
|
|
|
assert(VTableUses.empty() &&
|
|
|
|
"VTableUses should be empty before it is discarded, "
|
|
|
|
"while instantiating static data member.");
|
|
|
|
VTableUses.swap(SavedVTableUses);
|
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// Restore the set of pending implicit instantiations.
|
2011-05-31 15:58:42 +08:00
|
|
|
assert(PendingInstantiations.empty() &&
|
|
|
|
"PendingInstantiations should be empty before it is discarded, "
|
|
|
|
"while instantiating static data member.");
|
2010-08-25 16:44:16 +08:00
|
|
|
PendingInstantiations.swap(SavedPendingInstantiations);
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-05-14 04:28:22 +08:00
|
|
|
}
|
2009-05-27 13:35:12 +08:00
|
|
|
|
2009-08-29 13:16:22 +08:00
|
|
|
void
|
|
|
|
Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
|
|
|
|
const CXXConstructorDecl *Tmpl,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-09-09 11:18:59 +08:00
|
|
|
SmallVector<CXXCtorInitializer*, 4> NewInits;
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
bool AnyErrors = false;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-08-29 13:16:22 +08:00
|
|
|
// Instantiate all the initializers.
|
|
|
|
for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
|
2009-09-02 05:04:42 +08:00
|
|
|
InitsEnd = Tmpl->init_end();
|
|
|
|
Inits != InitsEnd; ++Inits) {
|
2011-01-09 04:30:50 +08:00
|
|
|
CXXCtorInitializer *Init = *Inits;
|
2009-08-29 13:16:22 +08:00
|
|
|
|
2010-09-04 05:54:20 +08:00
|
|
|
// Only instantiate written initializers, let Sema re-construct implicit
|
|
|
|
// ones.
|
|
|
|
if (!Init->isWritten())
|
|
|
|
continue;
|
|
|
|
|
2011-01-04 08:32:56 +08:00
|
|
|
SourceLocation EllipsisLoc;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-04 08:32:56 +08:00
|
|
|
if (Init->isPackExpansion()) {
|
|
|
|
// This is a pack expansion. We should expand it now.
|
2011-11-01 09:16:03 +08:00
|
|
|
TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc();
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
|
2011-01-04 08:32:56 +08:00
|
|
|
collectUnexpandedParameterPacks(BaseTL, Unexpanded);
|
|
|
|
bool ShouldExpand = false;
|
Work-in-progress implementation of C++0x [temp.arg.explicit]p9, which
allows an argument pack determines via explicit specification of
function template arguments to be extended by further, deduced
arguments. For example:
template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
}
There are a number of FIXMEs in here that indicate places where we
need to implement + test retained expansions, plus a number of other
places in deduction where we need to correctly cope with the
explicitly-specified arguments when deducing an argument
pack. Furthermore, it appears that the RecursiveASTVisitor needs to be
auditied; it's missing some traversals (especially w.r.t. template
arguments) that cause it not to find unexpanded parameter packs when
it should.
The good news, however, is that the tr1::tuple implementation now
works fully, and the tr1::bind example (both from N2080) is actually
working now.
llvm-svn: 123163
2011-01-10 15:32:04 +08:00
|
|
|
bool RetainExpansion = false;
|
2011-01-15 01:04:44 +08:00
|
|
|
llvm::Optional<unsigned> NumExpansions;
|
2011-10-08 19:31:46 +08:00
|
|
|
if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(),
|
2011-01-04 08:32:56 +08:00
|
|
|
BaseTL.getSourceRange(),
|
2011-09-22 10:34:54 +08:00
|
|
|
Unexpanded,
|
2011-10-08 19:31:46 +08:00
|
|
|
TemplateArgs, ShouldExpand,
|
Work-in-progress implementation of C++0x [temp.arg.explicit]p9, which
allows an argument pack determines via explicit specification of
function template arguments to be extended by further, deduced
arguments. For example:
template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
}
There are a number of FIXMEs in here that indicate places where we
need to implement + test retained expansions, plus a number of other
places in deduction where we need to correctly cope with the
explicitly-specified arguments when deducing an argument
pack. Furthermore, it appears that the RecursiveASTVisitor needs to be
auditied; it's missing some traversals (especially w.r.t. template
arguments) that cause it not to find unexpanded parameter packs when
it should.
The good news, however, is that the tr1::tuple implementation now
works fully, and the tr1::bind example (both from N2080) is actually
working now.
llvm-svn: 123163
2011-01-10 15:32:04 +08:00
|
|
|
RetainExpansion,
|
2011-01-04 08:32:56 +08:00
|
|
|
NumExpansions)) {
|
|
|
|
AnyErrors = true;
|
|
|
|
New->setInvalidDecl();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
assert(ShouldExpand && "Partial instantiation of base initializer?");
|
2011-10-08 19:31:46 +08:00
|
|
|
|
|
|
|
// Loop over all of the arguments in the argument pack(s),
|
2011-01-15 01:04:44 +08:00
|
|
|
for (unsigned I = 0; I != *NumExpansions; ++I) {
|
2011-01-04 08:32:56 +08:00
|
|
|
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
|
|
|
|
|
|
|
|
// Instantiate the initializer.
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs,
|
|
|
|
/*CXXDirectInit=*/true);
|
|
|
|
if (TempInit.isInvalid()) {
|
2011-01-04 08:32:56 +08:00
|
|
|
AnyErrors = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the base type.
|
2011-11-01 09:16:03 +08:00
|
|
|
TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(),
|
2011-10-08 19:31:46 +08:00
|
|
|
TemplateArgs,
|
|
|
|
Init->getSourceLocation(),
|
2011-01-04 08:32:56 +08:00
|
|
|
New->getDeclName());
|
|
|
|
if (!BaseTInfo) {
|
|
|
|
AnyErrors = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build the initializer.
|
2011-09-25 01:48:25 +08:00
|
|
|
MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(),
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
BaseTInfo, TempInit.take(),
|
2011-01-04 08:32:56 +08:00
|
|
|
New->getParent(),
|
|
|
|
SourceLocation());
|
|
|
|
if (NewInit.isInvalid()) {
|
|
|
|
AnyErrors = true;
|
|
|
|
break;
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-04 08:32:56 +08:00
|
|
|
NewInits.push_back(NewInit.get());
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-01-04 08:32:56 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-03-02 15:38:39 +08:00
|
|
|
// Instantiate the initializer.
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs,
|
|
|
|
/*CXXDirectInit=*/true);
|
|
|
|
if (TempInit.isInvalid()) {
|
2010-03-02 15:38:39 +08:00
|
|
|
AnyErrors = true;
|
|
|
|
continue;
|
2009-08-29 13:16:22 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-08-29 13:16:22 +08:00
|
|
|
MemInitResult NewInit;
|
2011-11-01 09:16:03 +08:00
|
|
|
if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) {
|
|
|
|
TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(),
|
|
|
|
TemplateArgs,
|
|
|
|
Init->getSourceLocation(),
|
|
|
|
New->getDeclName());
|
|
|
|
if (!TInfo) {
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
AnyErrors = true;
|
2009-12-03 06:36:29 +08:00
|
|
|
New->setInvalidDecl();
|
|
|
|
continue;
|
|
|
|
}
|
2011-09-25 01:48:25 +08:00
|
|
|
|
2011-11-01 09:16:03 +08:00
|
|
|
if (Init->isBaseInitializer())
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(),
|
2011-11-01 09:16:03 +08:00
|
|
|
New->getParent(), EllipsisLoc);
|
|
|
|
else
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(),
|
2011-11-01 09:16:03 +08:00
|
|
|
cast<CXXRecordDecl>(CurContext->getParent()));
|
2009-08-29 13:16:22 +08:00
|
|
|
} else if (Init->isMemberInitializer()) {
|
2011-03-05 03:46:35 +08:00
|
|
|
FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(
|
2010-12-04 17:14:42 +08:00
|
|
|
Init->getMemberLocation(),
|
|
|
|
Init->getMember(),
|
|
|
|
TemplateArgs));
|
2011-03-05 03:46:35 +08:00
|
|
|
if (!Member) {
|
|
|
|
AnyErrors = true;
|
|
|
|
New->setInvalidDecl();
|
|
|
|
continue;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
NewInit = BuildMemberInitializer(Member, TempInit.take(),
|
2011-09-25 01:48:25 +08:00
|
|
|
Init->getSourceLocation());
|
2010-12-04 17:14:42 +08:00
|
|
|
} else if (Init->isIndirectMemberInitializer()) {
|
|
|
|
IndirectFieldDecl *IndirectMember =
|
2011-03-05 03:46:35 +08:00
|
|
|
cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl(
|
2010-12-04 17:14:42 +08:00
|
|
|
Init->getMemberLocation(),
|
|
|
|
Init->getIndirectMember(), TemplateArgs));
|
|
|
|
|
2011-03-05 03:46:35 +08:00
|
|
|
if (!IndirectMember) {
|
|
|
|
AnyErrors = true;
|
|
|
|
New->setInvalidDecl();
|
2011-09-25 01:48:25 +08:00
|
|
|
continue;
|
2011-03-05 03:46:35 +08:00
|
|
|
}
|
2011-09-25 01:48:25 +08:00
|
|
|
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(),
|
2011-09-25 01:48:25 +08:00
|
|
|
Init->getSourceLocation());
|
2009-08-29 13:16:22 +08:00
|
|
|
}
|
|
|
|
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
if (NewInit.isInvalid()) {
|
|
|
|
AnyErrors = true;
|
2009-08-29 13:16:22 +08:00
|
|
|
New->setInvalidDecl();
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
} else {
|
2011-09-09 11:18:59 +08:00
|
|
|
NewInits.push_back(NewInit.get());
|
2009-08-29 13:16:22 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-29 13:16:22 +08:00
|
|
|
// Assign all the initializers to the new constructor.
|
2010-08-21 17:40:31 +08:00
|
|
|
ActOnMemInitializers(New,
|
2009-08-29 13:16:22 +08:00
|
|
|
/*FIXME: ColonLoc */
|
|
|
|
SourceLocation(),
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
NewInits.data(), NewInits.size(),
|
|
|
|
AnyErrors);
|
2009-08-29 13:16:22 +08:00
|
|
|
}
|
|
|
|
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
ExprResult Sema::SubstInitializer(Expr *Init,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
|
|
|
bool CXXDirectInit) {
|
|
|
|
// Initializers are instantiated like expressions, except that various outer
|
|
|
|
// layers are stripped.
|
|
|
|
if (!Init)
|
|
|
|
return Owned(Init);
|
|
|
|
|
|
|
|
if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
|
|
|
|
Init = ExprTemp->getSubExpr();
|
|
|
|
|
|
|
|
while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init))
|
|
|
|
Init = Binder->getSubExpr();
|
|
|
|
|
|
|
|
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init))
|
|
|
|
Init = ICE->getSubExprAsWritten();
|
|
|
|
|
|
|
|
// If this is a direct-initializer, we take apart CXXConstructExprs.
|
|
|
|
// Everything else is passed through.
|
|
|
|
CXXConstructExpr *Construct;
|
|
|
|
if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) ||
|
|
|
|
isa<CXXTemporaryObjectExpr>(Construct))
|
|
|
|
return SubstExpr(Init, TemplateArgs);
|
|
|
|
|
|
|
|
ASTOwningVector<Expr*> NewArgs(*this);
|
|
|
|
if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true,
|
|
|
|
TemplateArgs, NewArgs))
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
// Treat an empty initializer like none.
|
|
|
|
if (NewArgs.empty())
|
|
|
|
return Owned((Expr*)0);
|
|
|
|
|
|
|
|
// Build a ParenListExpr to represent anything else.
|
|
|
|
// FIXME: Fake locations!
|
|
|
|
SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart());
|
|
|
|
return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs));
|
|
|
|
}
|
|
|
|
|
2009-08-29 16:11:13 +08:00
|
|
|
// TODO: this could be templated if the various decl types used the
|
|
|
|
// same method name.
|
|
|
|
static bool isInstantiationOf(ClassTemplateDecl *Pattern,
|
|
|
|
ClassTemplateDecl *Instance) {
|
|
|
|
Pattern = Pattern->getCanonicalDecl();
|
|
|
|
|
|
|
|
do {
|
|
|
|
Instance = Instance->getCanonicalDecl();
|
|
|
|
if (Pattern == Instance) return true;
|
|
|
|
Instance = Instance->getInstantiatedFromMemberTemplate();
|
|
|
|
} while (Instance);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-09-28 14:34:35 +08:00
|
|
|
static bool isInstantiationOf(FunctionTemplateDecl *Pattern,
|
|
|
|
FunctionTemplateDecl *Instance) {
|
|
|
|
Pattern = Pattern->getCanonicalDecl();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-09-28 14:34:35 +08:00
|
|
|
do {
|
|
|
|
Instance = Instance->getCanonicalDecl();
|
|
|
|
if (Pattern == Instance) return true;
|
|
|
|
Instance = Instance->getInstantiatedFromMemberTemplate();
|
|
|
|
} while (Instance);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-09-28 14:34:35 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-10-08 19:31:46 +08:00
|
|
|
static bool
|
2009-10-29 08:04:11 +08:00
|
|
|
isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern,
|
|
|
|
ClassTemplatePartialSpecializationDecl *Instance) {
|
2011-10-08 19:31:46 +08:00
|
|
|
Pattern
|
2009-10-29 08:04:11 +08:00
|
|
|
= cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl());
|
|
|
|
do {
|
|
|
|
Instance = cast<ClassTemplatePartialSpecializationDecl>(
|
|
|
|
Instance->getCanonicalDecl());
|
|
|
|
if (Pattern == Instance)
|
|
|
|
return true;
|
|
|
|
Instance = Instance->getInstantiatedFromMember();
|
|
|
|
} while (Instance);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-08-29 16:11:13 +08:00
|
|
|
static bool isInstantiationOf(CXXRecordDecl *Pattern,
|
|
|
|
CXXRecordDecl *Instance) {
|
|
|
|
Pattern = Pattern->getCanonicalDecl();
|
|
|
|
|
|
|
|
do {
|
|
|
|
Instance = Instance->getCanonicalDecl();
|
|
|
|
if (Pattern == Instance) return true;
|
|
|
|
Instance = Instance->getInstantiatedFromMemberClass();
|
|
|
|
} while (Instance);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isInstantiationOf(FunctionDecl *Pattern,
|
|
|
|
FunctionDecl *Instance) {
|
|
|
|
Pattern = Pattern->getCanonicalDecl();
|
|
|
|
|
|
|
|
do {
|
|
|
|
Instance = Instance->getCanonicalDecl();
|
|
|
|
if (Pattern == Instance) return true;
|
|
|
|
Instance = Instance->getInstantiatedFromMemberFunction();
|
|
|
|
} while (Instance);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isInstantiationOf(EnumDecl *Pattern,
|
|
|
|
EnumDecl *Instance) {
|
|
|
|
Pattern = Pattern->getCanonicalDecl();
|
|
|
|
|
|
|
|
do {
|
|
|
|
Instance = Instance->getCanonicalDecl();
|
|
|
|
if (Pattern == Instance) return true;
|
|
|
|
Instance = Instance->getInstantiatedFromMemberEnum();
|
|
|
|
} while (Instance);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
static bool isInstantiationOf(UsingShadowDecl *Pattern,
|
|
|
|
UsingShadowDecl *Instance,
|
|
|
|
ASTContext &C) {
|
|
|
|
return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isInstantiationOf(UsingDecl *Pattern,
|
|
|
|
UsingDecl *Instance,
|
|
|
|
ASTContext &C) {
|
|
|
|
return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
|
|
|
|
}
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
|
|
|
|
UsingDecl *Instance,
|
|
|
|
ASTContext &C) {
|
2009-12-05 06:46:56 +08:00
|
|
|
return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
|
2009-11-18 10:36:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
|
2009-08-30 03:37:28 +08:00
|
|
|
UsingDecl *Instance,
|
|
|
|
ASTContext &C) {
|
2009-12-05 06:46:56 +08:00
|
|
|
return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
|
2009-08-30 03:37:28 +08:00
|
|
|
}
|
|
|
|
|
2009-08-29 16:11:13 +08:00
|
|
|
static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
|
|
|
|
VarDecl *Instance) {
|
|
|
|
assert(Instance->isStaticDataMember());
|
|
|
|
|
|
|
|
Pattern = Pattern->getCanonicalDecl();
|
|
|
|
|
|
|
|
do {
|
|
|
|
Instance = Instance->getCanonicalDecl();
|
|
|
|
if (Pattern == Instance) return true;
|
|
|
|
Instance = Instance->getInstantiatedFromStaticDataMember();
|
|
|
|
} while (Instance);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
// Other is the prospective instantiation
|
|
|
|
// D is the prospective pattern
|
2009-05-27 13:35:12 +08:00
|
|
|
static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
|
2009-08-30 03:37:28 +08:00
|
|
|
if (D->getKind() != Other->getKind()) {
|
2009-11-18 10:36:19 +08:00
|
|
|
if (UnresolvedUsingTypenameDecl *UUD
|
|
|
|
= dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
|
|
|
|
if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
|
|
|
|
return isInstantiationOf(UUD, UD, Ctx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UnresolvedUsingValueDecl *UUD
|
|
|
|
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
|
2009-08-30 03:37:28 +08:00
|
|
|
if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
|
|
|
|
return isInstantiationOf(UUD, UD, Ctx);
|
|
|
|
}
|
|
|
|
}
|
2009-05-27 13:35:12 +08:00
|
|
|
|
2009-08-30 03:37:28 +08:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-29 16:11:13 +08:00
|
|
|
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-29 16:11:13 +08:00
|
|
|
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<FunctionDecl>(D), Function);
|
2009-05-27 13:35:12 +08:00
|
|
|
|
2009-08-29 16:11:13 +08:00
|
|
|
if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<EnumDecl>(D), Enum);
|
2009-05-27 13:35:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
if (VarDecl *Var = dyn_cast<VarDecl>(Other))
|
2009-08-29 16:11:13 +08:00
|
|
|
if (Var->isStaticDataMember())
|
|
|
|
return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
|
|
|
|
|
|
|
|
if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
|
2009-08-29 06:03:51 +08:00
|
|
|
|
2009-09-28 14:34:35 +08:00
|
|
|
if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp);
|
|
|
|
|
2009-10-29 08:04:11 +08:00
|
|
|
if (ClassTemplatePartialSpecializationDecl *PartialSpec
|
|
|
|
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D),
|
|
|
|
PartialSpec);
|
|
|
|
|
2009-09-01 12:26:58 +08:00
|
|
|
if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) {
|
|
|
|
if (!Field->getDeclName()) {
|
|
|
|
// This is an unnamed field.
|
2009-09-09 23:08:12 +08:00
|
|
|
return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) ==
|
2009-09-01 12:26:58 +08:00
|
|
|
cast<FieldDecl>(D);
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-05 06:46:56 +08:00
|
|
|
if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
|
|
|
|
|
|
|
|
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
|
|
|
|
return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
|
|
|
|
|
2009-05-27 13:35:12 +08:00
|
|
|
return D->getDeclName() && isa<NamedDecl>(Other) &&
|
|
|
|
D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename ForwardIterator>
|
2009-09-09 23:08:12 +08:00
|
|
|
static NamedDecl *findInstantiationOf(ASTContext &Ctx,
|
2009-05-27 13:35:12 +08:00
|
|
|
NamedDecl *D,
|
|
|
|
ForwardIterator first,
|
|
|
|
ForwardIterator last) {
|
|
|
|
for (; first != last; ++first)
|
|
|
|
if (isInstantiationOf(Ctx, D, *first))
|
|
|
|
return cast<NamedDecl>(*first);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-08-28 15:59:38 +08:00
|
|
|
/// \brief Finds the instantiation of the given declaration context
|
|
|
|
/// within the current instantiation.
|
|
|
|
///
|
|
|
|
/// \returns NULL if there was an error
|
2010-03-01 23:56:25 +08:00
|
|
|
DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC,
|
2009-09-17 02:34:49 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-08-28 15:59:38 +08:00
|
|
|
if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) {
|
2010-03-01 23:56:25 +08:00
|
|
|
Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs);
|
2009-08-28 15:59:38 +08:00
|
|
|
return cast_or_null<DeclContext>(ID);
|
|
|
|
} else return DC;
|
|
|
|
}
|
|
|
|
|
2009-05-28 01:54:46 +08:00
|
|
|
/// \brief Find the instantiation of the given declaration within the
|
|
|
|
/// current instantiation.
|
2009-05-27 13:35:12 +08:00
|
|
|
///
|
|
|
|
/// This routine is intended to be used when \p D is a declaration
|
|
|
|
/// referenced from within a template, that needs to mapped into the
|
|
|
|
/// corresponding declaration within an instantiation. For example,
|
|
|
|
/// given:
|
|
|
|
///
|
|
|
|
/// \code
|
|
|
|
/// template<typename T>
|
|
|
|
/// struct X {
|
|
|
|
/// enum Kind {
|
|
|
|
/// KnownValue = sizeof(T)
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// bool getKind() const { return KnownValue; }
|
|
|
|
/// };
|
|
|
|
///
|
|
|
|
/// template struct X<int>;
|
|
|
|
/// \endcode
|
|
|
|
///
|
|
|
|
/// In the instantiation of X<int>::getKind(), we need to map the
|
|
|
|
/// EnumConstantDecl for KnownValue (which refers to
|
2012-06-17 11:36:08 +08:00
|
|
|
/// X<T>::\<Kind>\::KnownValue) to its instantiation
|
2012-06-16 06:23:43 +08:00
|
|
|
/// (X<int>::\<Kind>\::KnownValue). InstantiateCurrentDeclRef() performs
|
2009-05-28 01:54:46 +08:00
|
|
|
/// this mapping from within the instantiation of X<int>.
|
2010-03-01 23:56:25 +08:00
|
|
|
NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
2009-09-17 02:34:49 +08:00
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
2009-05-27 13:35:12 +08:00
|
|
|
DeclContext *ParentDC = D->getDeclContext();
|
2009-11-01 01:21:17 +08:00
|
|
|
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
|
2010-02-06 03:54:12 +08:00
|
|
|
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
|
2012-02-17 05:36:18 +08:00
|
|
|
(ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
|
|
|
|
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
|
2009-05-28 01:07:49 +08:00
|
|
|
// D is a local of some kind. Look into the map of local
|
|
|
|
// declarations to their instantiations.
|
2011-02-18 03:47:42 +08:00
|
|
|
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
|
|
|
|
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
|
|
|
|
= CurrentInstantiationScope->findInstantiationOf(D);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
if (Found) {
|
|
|
|
if (Decl *FD = Found->dyn_cast<Decl *>())
|
|
|
|
return cast<NamedDecl>(FD);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
unsigned PackIdx = ArgumentPackSubstitutionIndex;
|
|
|
|
return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we didn't find the decl, then we must have a label decl that hasn't
|
|
|
|
// been found yet. Lazily instantiate it and return it now.
|
|
|
|
assert(isa<LabelDecl>(D));
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
Decl *Inst = SubstDecl(D, CurContext, TemplateArgs);
|
|
|
|
assert(Inst && "Failed to instantiate label??");
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
CurrentInstantiationScope->InstantiatedLocal(D, Inst);
|
|
|
|
return cast<LabelDecl>(Inst);
|
2009-05-28 01:07:49 +08:00
|
|
|
}
|
2009-05-27 13:35:12 +08:00
|
|
|
|
2009-09-17 02:34:49 +08:00
|
|
|
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
|
|
|
|
if (!Record->isDependentContext())
|
|
|
|
return D;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-11-08 01:43:18 +08:00
|
|
|
// Determine whether this record is the "templated" declaration describing
|
|
|
|
// a class template or class template partial specialization.
|
2009-09-17 02:34:49 +08:00
|
|
|
ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
|
2011-11-08 01:43:18 +08:00
|
|
|
if (ClassTemplate)
|
|
|
|
ClassTemplate = ClassTemplate->getCanonicalDecl();
|
|
|
|
else if (ClassTemplatePartialSpecializationDecl *PartialSpec
|
|
|
|
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
|
|
|
|
ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
|
|
|
|
|
|
|
|
// Walk the current context to find either the record or an instantiation of
|
|
|
|
// it.
|
|
|
|
DeclContext *DC = CurContext;
|
|
|
|
while (!DC->isFileContext()) {
|
|
|
|
// If we're performing substitution while we're inside the template
|
|
|
|
// definition, we'll find our own context. We're done.
|
|
|
|
if (DC->Equals(Record))
|
|
|
|
return Record;
|
|
|
|
|
|
|
|
if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
|
|
|
|
// Check whether we're in the process of instantiating a class template
|
|
|
|
// specialization of the template we're mapping.
|
|
|
|
if (ClassTemplateSpecializationDecl *InstSpec
|
|
|
|
= dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){
|
|
|
|
ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate();
|
|
|
|
if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
|
|
|
|
return InstRecord;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether we're in the process of instantiating a member class.
|
|
|
|
if (isInstantiationOf(Record, InstRecord))
|
|
|
|
return InstRecord;
|
2009-09-17 02:34:49 +08:00
|
|
|
}
|
2011-11-08 01:43:18 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Move to the outer template scope.
|
|
|
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
|
|
|
|
if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
|
|
|
|
DC = FD->getLexicalDeclContext();
|
|
|
|
continue;
|
|
|
|
}
|
2009-08-29 16:11:13 +08:00
|
|
|
}
|
2011-11-08 01:43:18 +08:00
|
|
|
|
|
|
|
DC = DC->getParent();
|
2009-08-29 16:11:13 +08:00
|
|
|
}
|
2010-02-06 06:40:03 +08:00
|
|
|
|
2009-09-17 02:34:49 +08:00
|
|
|
// Fall through to deal with other dependent record types (e.g.,
|
|
|
|
// anonymous unions in class templates).
|
|
|
|
}
|
2009-08-29 16:11:13 +08:00
|
|
|
|
2009-09-17 02:34:49 +08:00
|
|
|
if (!ParentDC->isDependentContext())
|
|
|
|
return D;
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-03-01 23:56:25 +08:00
|
|
|
ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs);
|
2009-09-09 23:08:12 +08:00
|
|
|
if (!ParentDC)
|
2009-09-02 01:53:10 +08:00
|
|
|
return 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-27 13:35:12 +08:00
|
|
|
if (ParentDC != D->getDeclContext()) {
|
|
|
|
// We performed some kind of instantiation in the parent context,
|
|
|
|
// so now we need to look into the instantiated parent context to
|
|
|
|
// find the instantiation of the declaration D.
|
2010-03-01 23:56:25 +08:00
|
|
|
|
2010-03-10 11:28:59 +08:00
|
|
|
// If our context used to be dependent, we may need to instantiate
|
|
|
|
// it before performing lookup into that context.
|
2011-03-07 04:12:45 +08:00
|
|
|
bool IsBeingInstantiated = false;
|
2010-03-10 11:28:59 +08:00
|
|
|
if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
|
2010-03-01 23:56:25 +08:00
|
|
|
if (!Spec->isDependentContext()) {
|
|
|
|
QualType T = Context.getTypeDeclType(Spec);
|
2010-03-10 11:28:59 +08:00
|
|
|
const RecordType *Tag = T->getAs<RecordType>();
|
|
|
|
assert(Tag && "type of non-dependent record is not a RecordType");
|
2011-03-07 04:12:45 +08:00
|
|
|
if (Tag->isBeingDefined())
|
|
|
|
IsBeingInstantiated = true;
|
2010-03-10 11:28:59 +08:00
|
|
|
if (!Tag->isBeingDefined() &&
|
|
|
|
RequireCompleteType(Loc, T, diag::err_incomplete_type))
|
|
|
|
return 0;
|
2010-11-06 07:22:45 +08:00
|
|
|
|
|
|
|
ParentDC = Tag->getDecl();
|
2010-03-01 23:56:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-27 13:35:12 +08:00
|
|
|
NamedDecl *Result = 0;
|
|
|
|
if (D->getDeclName()) {
|
2009-06-30 10:36:12 +08:00
|
|
|
DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName());
|
2009-05-27 13:35:12 +08:00
|
|
|
Result = findInstantiationOf(Context, D, Found.first, Found.second);
|
|
|
|
} else {
|
|
|
|
// Since we don't have a name for the entity we're looking for,
|
|
|
|
// our only option is to walk through all of the declarations to
|
|
|
|
// find that name. This will occur in a few cases:
|
|
|
|
//
|
|
|
|
// - anonymous struct/union within a template
|
|
|
|
// - unnamed class/struct/union/enum within a template
|
|
|
|
//
|
|
|
|
// FIXME: Find a better way to find these instantiations!
|
2009-09-09 23:08:12 +08:00
|
|
|
Result = findInstantiationOf(Context, D,
|
2009-06-30 10:36:12 +08:00
|
|
|
ParentDC->decls_begin(),
|
|
|
|
ParentDC->decls_end());
|
2009-05-27 13:35:12 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-03-07 04:12:45 +08:00
|
|
|
if (!Result) {
|
|
|
|
if (isa<UsingShadowDecl>(D)) {
|
|
|
|
// UsingShadowDecls can instantiate to nothing because of using hiding.
|
|
|
|
} else if (Diags.hasErrorOccurred()) {
|
|
|
|
// We've already complained about something, so most likely this
|
|
|
|
// declaration failed to instantiate. There's no point in complaining
|
|
|
|
// further, since this is normal in invalid code.
|
|
|
|
} else if (IsBeingInstantiated) {
|
2011-10-08 19:31:46 +08:00
|
|
|
// The class in which this member exists is currently being
|
2011-03-07 04:12:45 +08:00
|
|
|
// instantiated, and we haven't gotten around to instantiating this
|
|
|
|
// member yet. This can happen when the code uses forward declarations
|
|
|
|
// of member classes, and introduces ordering dependencies via
|
|
|
|
// template instantiation.
|
|
|
|
Diag(Loc, diag::err_member_not_yet_instantiated)
|
|
|
|
<< D->getDeclName()
|
|
|
|
<< Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC));
|
|
|
|
Diag(D->getLocation(), diag::note_non_instantiated_member_here);
|
2012-03-27 04:28:16 +08:00
|
|
|
} else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
|
|
|
|
// This enumeration constant was found when the template was defined,
|
|
|
|
// but can't be found in the instantiation. This can happen if an
|
|
|
|
// unscoped enumeration member is explicitly specialized.
|
|
|
|
EnumDecl *Enum = cast<EnumDecl>(ED->getLexicalDeclContext());
|
|
|
|
EnumDecl *Spec = cast<EnumDecl>(FindInstantiatedDecl(Loc, Enum,
|
|
|
|
TemplateArgs));
|
|
|
|
assert(Spec->getTemplateSpecializationKind() ==
|
|
|
|
TSK_ExplicitSpecialization);
|
|
|
|
Diag(Loc, diag::err_enumerator_does_not_exist)
|
|
|
|
<< D->getDeclName()
|
|
|
|
<< Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext()));
|
|
|
|
Diag(Spec->getLocation(), diag::note_enum_specialized_here)
|
|
|
|
<< Context.getTypeDeclType(Spec);
|
2011-03-07 04:12:45 +08:00
|
|
|
} else {
|
|
|
|
// We should have found something, but didn't.
|
|
|
|
llvm_unreachable("Unable to find instantiation of declaration!");
|
|
|
|
}
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-05-27 13:35:12 +08:00
|
|
|
D = Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return D;
|
|
|
|
}
|
2009-06-23 07:06:13 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// \brief Performs template instantiation for all implicit template
|
2009-06-23 07:06:13 +08:00
|
|
|
/// instantiations we have seen until this point.
|
2011-05-31 15:58:42 +08:00
|
|
|
void Sema::PerformPendingInstantiations(bool LocalOnly) {
|
2011-07-29 03:49:54 +08:00
|
|
|
// Load pending instantiations from the external source.
|
|
|
|
if (!LocalOnly && ExternalSource) {
|
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
|
|
|
SmallVector<PendingImplicitInstantiation, 4> Pending;
|
2011-07-29 03:49:54 +08:00
|
|
|
ExternalSource->ReadPendingInstantiations(Pending);
|
|
|
|
PendingInstantiations.insert(PendingInstantiations.begin(),
|
|
|
|
Pending.begin(), Pending.end());
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-01-17 06:29:39 +08:00
|
|
|
while (!PendingLocalImplicitInstantiations.empty() ||
|
2010-08-25 16:44:16 +08:00
|
|
|
(!LocalOnly && !PendingInstantiations.empty())) {
|
2010-01-17 06:29:39 +08:00
|
|
|
PendingImplicitInstantiation Inst;
|
|
|
|
|
|
|
|
if (PendingLocalImplicitInstantiations.empty()) {
|
2010-08-25 16:44:16 +08:00
|
|
|
Inst = PendingInstantiations.front();
|
|
|
|
PendingInstantiations.pop_front();
|
2010-01-17 06:29:39 +08:00
|
|
|
} else {
|
|
|
|
Inst = PendingLocalImplicitInstantiations.front();
|
|
|
|
PendingLocalImplicitInstantiations.pop_front();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// Instantiate function definitions
|
|
|
|
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
|
2010-08-27 07:41:50 +08:00
|
|
|
PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
|
|
|
|
"instantiating function definition");
|
2010-08-25 16:27:02 +08:00
|
|
|
bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
|
|
|
|
TSK_ExplicitInstantiationDefinition;
|
|
|
|
InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
|
|
|
|
DefinitionRequired);
|
2009-07-25 04:34:43 +08:00
|
|
|
continue;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-25 04:34:43 +08:00
|
|
|
// Instantiate static data member definitions.
|
|
|
|
VarDecl *Var = cast<VarDecl>(Inst.first);
|
|
|
|
assert(Var->isStaticDataMember() && "Not a static data member?");
|
2009-09-01 13:12:24 +08:00
|
|
|
|
2010-02-13 18:17:50 +08:00
|
|
|
// Don't try to instantiate declarations if the most recent redeclaration
|
|
|
|
// is invalid.
|
2012-01-15 00:38:05 +08:00
|
|
|
if (Var->getMostRecentDecl()->isInvalidDecl())
|
2010-02-13 18:17:50 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Check if the most recent declaration has changed the specialization kind
|
|
|
|
// and removed the need for implicit instantiation.
|
2012-01-15 00:38:05 +08:00
|
|
|
switch (Var->getMostRecentDecl()->getTemplateSpecializationKind()) {
|
2010-02-13 18:17:50 +08:00
|
|
|
case TSK_Undeclared:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("Cannot instantitiate an undeclared specialization.");
|
2010-02-13 18:17:50 +08:00
|
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
|
|
case TSK_ExplicitSpecialization:
|
2010-08-25 16:27:02 +08:00
|
|
|
continue; // No longer need to instantiate this type.
|
|
|
|
case TSK_ExplicitInstantiationDefinition:
|
|
|
|
// We only need an instantiation if the pending instantiation *is* the
|
|
|
|
// explicit instantiation.
|
2012-01-15 00:38:05 +08:00
|
|
|
if (Var != Var->getMostRecentDecl()) continue;
|
2010-02-13 18:17:50 +08:00
|
|
|
case TSK_ImplicitInstantiation:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-08-27 07:41:50 +08:00
|
|
|
PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(),
|
|
|
|
"instantiating static data member "
|
|
|
|
"definition");
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-25 16:27:02 +08:00
|
|
|
bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
|
|
|
|
TSK_ExplicitInstantiationDefinition;
|
|
|
|
InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
|
|
|
|
DefinitionRequired);
|
2009-06-23 07:06:13 +08:00
|
|
|
}
|
|
|
|
}
|
2010-03-24 13:22:00 +08:00
|
|
|
|
|
|
|
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
|
|
|
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
|
|
|
for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(),
|
|
|
|
E = Pattern->ddiag_end(); I != E; ++I) {
|
|
|
|
DependentDiagnostic *DD = *I;
|
|
|
|
|
|
|
|
switch (DD->getKind()) {
|
|
|
|
case DependentDiagnostic::Access:
|
|
|
|
HandleDependentAccessCheck(*DD, TemplateArgs);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|