summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-04-16 07:05:22 +0000
committerDouglas Gregor <dgregor@apple.com>2012-04-16 07:05:22 +0000
commit3024f07c12324a85c3713a9be361402eed74e547 (patch)
tree9e2046728df1ce9faef7782dc8f873136d68eabf /clang/lib/Sema/SemaTemplateInstantiate.cpp
parent26d7a949819fb4bd7dba0853759d0b6bf6b47eee (diff)
downloadbcm5719-llvm-3024f07c12324a85c3713a9be361402eed74e547.tar.gz
bcm5719-llvm-3024f07c12324a85c3713a9be361402eed74e547.zip
Implement C++11 [expr.prim.general]p3, which permits the use of 'this'
in the declaration of a non-static member function after the (optional) cv-qualifier-seq, which in practice means in the exception specification and late-specified return type. The new scheme here used to manage 'this' outside of a member function scope is more general than the Scope-based mechanism previously used for non-static data member initializers and late-parsesd attributes, because it can also handle the cv-qualifiers on the member function. Note, however, that a separate pass is required for static member functions to determine whether 'this' was used, because we might not know that we have a static function until after declaration matching. Finally, this introduces name mangling for 'this' and for the implicit 'this', which is intended to match GCC's mangling. Independent verification for the new mangling test case would be appreciated. Fixes PR10036 and PR12450. llvm-svn: 154799
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp69
1 files changed, 51 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 4740145fd5a..60de75b9172 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -789,6 +789,11 @@ namespace {
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL);
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions,
@@ -1211,6 +1216,16 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
return inherited::TransformFunctionProtoType(TLB, TL);
}
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
+ // We need a local instantiation scope for this function prototype.
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ return inherited::TransformFunctionProtoType(TLB, TL, ThisContext,
+ ThisTypeQuals);
+}
+
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
@@ -1446,7 +1461,9 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
- DeclarationName Entity) {
+ DeclarationName Entity,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
assert(!ActiveTemplateInstantiations.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
@@ -1461,7 +1478,14 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
TypeLoc TL = T->getTypeLoc();
TLB.reserve(TL.getFullDataSize());
- QualType Result = Instantiator.TransformType(TLB, TL);
+ QualType Result;
+
+ if (FunctionProtoTypeLoc *Proto = dyn_cast<FunctionProtoTypeLoc>(&TL)) {
+ Result = Instantiator.TransformFunctionProtoType(TLB, *Proto, ThisContext,
+ ThisTypeQuals);
+ } else {
+ Result = Instantiator.TransformType(TLB, TL);
+ }
if (Result.isNull())
return 0;
@@ -1878,24 +1902,33 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CheckCompletedCXXClass(Instantiation);
// Attach any in-class member initializers now the class is complete.
- for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
- FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
- FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
- Expr *OldInit = OldField->getInClassInitializer();
-
- ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
- /*CXXDirectInit=*/false);
- if (NewInit.isInvalid())
- NewField->setInvalidDecl();
- else {
- Expr *Init = NewInit.take();
- assert(Init && "no-argument initializer in class");
- assert(!isa<ParenListExpr>(Init) && "call-style init in class");
- ActOnCXXInClassMemberInitializer(NewField,
- Init->getSourceRange().getBegin(), Init);
+ {
+ // C++11 [expr.prim.general]p4:
+ // Otherwise, if a member-declarator declares a non-static data member
+ // (9.2) of a class X, the expression this is a prvalue of type "pointer
+ // to X" within the optional brace-or-equal-initializer. It shall not
+ // appear elsewhere in the member-declarator.
+ CXXThisScopeRAII ThisScope(*this, Instantiation, (unsigned)0);
+
+ for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
+ FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
+ FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
+ Expr *OldInit = OldField->getInClassInitializer();
+
+ ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+ /*CXXDirectInit=*/false);
+ if (NewInit.isInvalid())
+ NewField->setInvalidDecl();
+ else {
+ Expr *Init = NewInit.take();
+ assert(Init && "no-argument initializer in class");
+ assert(!isa<ParenListExpr>(Init) && "call-style init in class");
+ ActOnCXXInClassMemberInitializer(NewField,
+ Init->getSourceRange().getBegin(),
+ Init);
+ }
}
}
-
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
OpenPOWER on IntegriCloud