summaryrefslogtreecommitdiffstats
path: root/lib/Sema
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
commitcefc3afac14d29de5aba7810cc8fe6c858949e9d (patch)
tree1ebfb2a0c67f5e253edc1a2900cdda348163f4f5 /lib/Sema
parent275a8505420733a9e4c662289f36522a1dabaa51 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154799 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.cpp1
-rw-r--r--lib/Sema/SemaDecl.cpp9
-rw-r--r--lib/Sema/SemaDeclCXX.cpp124
-rw-r--r--lib/Sema/SemaExprCXX.cpp60
-rw-r--r--lib/Sema/SemaExprMember.cpp17
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp49
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp69
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp27
-rw-r--r--lib/Sema/TreeTransform.h30
9 files changed, 325 insertions, 61 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fcdfcace0c..30a9cd751a 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -103,6 +103,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
AnalysisWarnings(*this)
{
TUScope = 0;
+
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = 0;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8b314b524f..1d4745dcaa 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5834,6 +5834,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
}
+
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionType(Method);
}
// Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -7554,7 +7557,11 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
// Always attach attributes to the underlying decl.
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
- ProcessDeclAttributeList(S, D, Attrs.getList());
+ ProcessDeclAttributeList(S, D, Attrs.getList());
+
+ if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionAttributes(Method);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 847f03c948..f488296336 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
@@ -11053,6 +11054,129 @@ void Sema::CheckDelegatingCtorCycles() {
(*CI)->setInvalidDecl();
}
+namespace {
+ /// \brief AST visitor that finds references to the 'this' expression.
+ class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
+ Sema &S;
+
+ public:
+ explicit FindCXXThisExpr(Sema &S) : S(S) { }
+
+ bool VisitCXXThisExpr(CXXThisExpr *E) {
+ S.Diag(E->getLocation(), diag::err_this_static_member_func)
+ << E->isImplicit();
+ return false;
+ }
+ };
+}
+
+bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
+ TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+ if (!TSInfo)
+ return false;
+
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ if (!ProtoTL)
+ return false;
+
+ // C++11 [expr.prim.general]p3:
+ // [The expression this] shall not appear before the optional
+ // cv-qualifier-seq and it shall not appear within the declaration of a
+ // static member function (although its type and value category are defined
+ // within a static member function as they are within a non-static member
+ // function). [ Note: this is because declaration matching does not occur
+ // until the complete declarator is known. — end note ]
+ const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ FindCXXThisExpr Finder(*this);
+
+ // If the return type came after the cv-qualifier-seq, check it now.
+ if (Proto->hasTrailingReturn() &&
+ !Finder.TraverseTypeLoc(ProtoTL->getResultLoc()))
+ return true;
+
+ // Check the exception specification.
+ switch (Proto->getExceptionSpecType()) {
+ case EST_BasicNoexcept:
+ case EST_Delayed:
+ case EST_DynamicNone:
+ case EST_MSAny:
+ case EST_None:
+ break;
+
+ case EST_ComputedNoexcept:
+ if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
+ return true;
+
+ case EST_Dynamic:
+ for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+ EEnd = Proto->exception_end();
+ E != EEnd; ++E) {
+ if (!Finder.TraverseType(*E))
+ return true;
+ }
+ break;
+ }
+
+ return checkThisInStaticMemberFunctionAttributes(Method);
+}
+
+bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
+ FindCXXThisExpr Finder(*this);
+
+ // Check attributes.
+ for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end();
+ A != AEnd; ++A) {
+ // FIXME: This should be emitted by tblgen.
+ Expr *Arg = 0;
+ ArrayRef<Expr *> Args;
+ if (GuardedByAttr *G = dyn_cast<GuardedByAttr>(*A))
+ Arg = G->getArg();
+ else if (PtGuardedByAttr *G = dyn_cast<PtGuardedByAttr>(*A))
+ Arg = G->getArg();
+ else if (AcquiredAfterAttr *AA = dyn_cast<AcquiredAfterAttr>(*A))
+ Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
+ else if (AcquiredBeforeAttr *AB = dyn_cast<AcquiredBeforeAttr>(*A))
+ Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
+ else if (ExclusiveLockFunctionAttr *ELF
+ = dyn_cast<ExclusiveLockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
+ else if (SharedLockFunctionAttr *SLF
+ = dyn_cast<SharedLockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
+ else if (ExclusiveTrylockFunctionAttr *ETLF
+ = dyn_cast<ExclusiveTrylockFunctionAttr>(*A)) {
+ Arg = ETLF->getSuccessValue();
+ Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
+ } else if (SharedTrylockFunctionAttr *STLF
+ = dyn_cast<SharedTrylockFunctionAttr>(*A)) {
+ Arg = STLF->getSuccessValue();
+ Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
+ } else if (UnlockFunctionAttr *UF = dyn_cast<UnlockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
+ else if (LockReturnedAttr *LR = dyn_cast<LockReturnedAttr>(*A))
+ Arg = LR->getArg();
+ else if (LocksExcludedAttr *LE = dyn_cast<LocksExcludedAttr>(*A))
+ Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
+ else if (ExclusiveLocksRequiredAttr *ELR
+ = dyn_cast<ExclusiveLocksRequiredAttr>(*A))
+ Args = ArrayRef<Expr *>(ELR->args_begin(), ELR->args_size());
+ else if (SharedLocksRequiredAttr *SLR
+ = dyn_cast<SharedLocksRequiredAttr>(*A))
+ Args = ArrayRef<Expr *>(SLR->args_begin(), SLR->args_size());
+
+ if (Arg && !Finder.TraverseStmt(Arg))
+ return true;
+
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ if (!Finder.TraverseStmt(Args[I]))
+ return true;
+ }
+ }
+
+ return false;
+}
+
/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
// Implicitly declared functions (e.g. copy constructors) are
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 31a8115f0b..e4b40e624c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -654,23 +654,44 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
QualType Sema::getCurrentThisType() {
DeclContext *DC = getFunctionLevelDeclContext();
- QualType ThisTy;
+ QualType ThisTy = CXXThisTypeOverride;
if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
if (method && method->isInstance())
ThisTy = method->getThisType(Context);
- } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
- // C++0x [expr.prim]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // of a class X, the expression this is a prvalue of type "pointer to X"
- // within the optional brace-or-equal-initializer.
- Scope *S = getScopeForContext(DC);
- if (!S || S->getFlags() & Scope::ThisScope)
- ThisTy = Context.getPointerType(Context.getRecordType(RD));
}
-
+
return ThisTy;
}
+Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
+ Decl *ContextDecl,
+ unsigned CXXThisTypeQuals,
+ bool Enabled)
+ : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
+{
+ if (!Enabled || !ContextDecl)
+ return;
+
+ CXXRecordDecl *Record = 0;
+ if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl))
+ Record = Template->getTemplatedDecl();
+ else
+ Record = cast<CXXRecordDecl>(ContextDecl);
+
+ S.CXXThisTypeOverride
+ = S.Context.getPointerType(
+ S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
+
+ this->Enabled = true;
+}
+
+
+Sema::CXXThisScopeRAII::~CXXThisScopeRAII() {
+ if (Enabled) {
+ S.CXXThisTypeOverride = OldCXXThisTypeOverride;
+ }
+}
+
void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
// We don't need to capture this in an unevaluated context.
if (ExprEvalContexts.back().Context == Unevaluated && !Explicit)
@@ -739,6 +760,18 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
}
+bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
+ // If we're outside the body of a member function, then we'll have a specified
+ // type for 'this'.
+ if (CXXThisTypeOverride.isNull())
+ return false;
+
+ // Determine whether we're looking into a class that's currently being
+ // defined.
+ CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl();
+ return Class && Class->isBeingDefined();
+}
+
ExprResult
Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
SourceLocation LParenLoc,
@@ -4784,8 +4817,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
return Owned(Base);
}
- // The object type must be complete (or dependent).
+ // The object type must be complete (or dependent), or
+ // C++11 [expr.prim.general]p3:
+ // Unlike the object expression in other contexts, *this is not required to
+ // be of complete type for purposes of class member access (5.2.5) outside
+ // the member function body.
if (!BaseType->isDependentType() &&
+ !isThisOutsideMemberFunctionBody(BaseType) &&
RequireCompleteType(OpLoc, BaseType,
PDiag(diag::err_incomplete_member_access)))
return ExprError();
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 26b88a2a7e..6c84caa3f3 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -101,16 +101,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
- bool isStaticContext =
- (!isa<CXXMethodDecl>(DC) ||
- cast<CXXMethodDecl>(DC)->isStatic());
-
- // C++0x [expr.prim]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // of a class X, the expression this is a prvalue of type "pointer to X"
- // within the optional brace-or-equal-initializer.
- if (CurScope->getFlags() & Scope::ThisScope)
- isStaticContext = false;
+ bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() &&
+ (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic());
if (R.isUnresolvableResult())
return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
@@ -549,12 +541,13 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
}
static bool
-LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
SourceRange BaseRange, const RecordType *RTy,
SourceLocation OpLoc, CXXScopeSpec &SS,
bool HasTemplateArgs) {
RecordDecl *RDecl = RTy->getDecl();
- if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+ if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
+ SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
<< BaseRange))
return true;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 2ea1e6ff93..d68e4642fc 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2310,23 +2310,42 @@ Sema::SubstituteExplicitTemplateArguments(
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute
// in lexical order.
- if (Proto->hasTrailingReturn() &&
- SubstParmTypes(Function->getLocation(),
- Function->param_begin(), Function->getNumParams(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- ParamTypes))
- return TDK_SubstitutionFailure;
-
+ if (Proto->hasTrailingReturn()) {
+ if (SubstParmTypes(Function->getLocation(),
+ Function->param_begin(), Function->getNumParams(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ ParamTypes))
+ return TDK_SubstitutionFailure;
+ }
+
// Instantiate the return type.
// FIXME: exception-specifications?
- QualType ResultType
- = SubstType(Proto->getResultType(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- Function->getTypeSpecStartLoc(),
- Function->getDeclName());
- if (ResultType.isNull() || Trap.hasErrorOccurred())
- return TDK_SubstitutionFailure;
-
+ QualType ResultType;
+ {
+ // 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.
+ unsigned ThisTypeQuals = 0;
+ CXXRecordDecl *ThisContext = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+
+ CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
+ getLangOpts().CPlusPlus0x);
+
+ ResultType = SubstType(Proto->getResultType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(),
+ Function->getDeclName());
+ if (ResultType.isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+ }
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments if we didn't do so earlier.
if (!Proto->hasTrailingReturn() &&
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4740145fd5..60de75b917 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/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(),
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8afe7aca97..8d382d1bac 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2141,10 +2141,19 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
assert(OldTInfo && "substituting function without type source info");
assert(Params.empty() && "parameter vector is non-empty at start");
+
+ CXXRecordDecl *ThisContext = 0;
+ unsigned ThisTypeQuals = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+
TypeSourceInfo *NewTInfo
= SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
D->getTypeSpecStartLoc(),
- D->getDeclName());
+ D->getDeclName(),
+ ThisContext, ThisTypeQuals);
if (!NewTInfo)
return 0;
@@ -2243,6 +2252,22 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(Proto && "Function template without prototype?");
if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
+ // 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;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index acfea6e3e4..5511fc00f5 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -522,6 +522,11 @@ public:
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+
StmtResult
TransformSEHHandler(Stmt *Handler);
@@ -4165,6 +4170,15 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
+ return getDerived().TransformFunctionProtoType(TLB, TL, 0, 0);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
// Transform the parameters and return type.
//
// We instantiate in source order, with the return type first followed by
@@ -4189,9 +4203,19 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParamTypes, &ParamDecls))
return QualType();
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
- if (ResultType.isNull())
- return QualType();
+ {
+ // 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.
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals);
+
+ ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+ }
}
else {
ResultType = getDerived().TransformType(TLB, TL.getResultLoc());