PR16243: Use CXXThisOverride during template instantiation, and fix up the
places which weren't setting it up properly. This allows us to get the right cv-qualifiers for 'this' when it appears outside a method body in a class template. llvm-svn: 183483
This commit is contained in:
@@ -1063,9 +1063,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
|
||||
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
|
||||
|
||||
// Allow 'this' within late-parsed attributes.
|
||||
Sema::CXXThisScopeRAII ThisScope(Actions, RD,
|
||||
/*TypeQuals=*/0,
|
||||
ND && RD && ND->isCXXInstanceMember());
|
||||
Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0,
|
||||
ND && ND->isCXXInstanceMember());
|
||||
|
||||
if (LA.Decls.size() == 1) {
|
||||
// If the Decl is templatized, add template parameters to scope.
|
||||
|
||||
@@ -2080,6 +2080,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
||||
E = LateAttrs.end(); I != E; ++I) {
|
||||
assert(CurrentInstantiationScope == Instantiator.getStartingScope());
|
||||
CurrentInstantiationScope = I->Scope;
|
||||
|
||||
// Allow 'this' within late-parsed attributes.
|
||||
NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
|
||||
CXXRecordDecl *ThisContext =
|
||||
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
||||
CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
|
||||
ND && ND->isCXXInstanceMember());
|
||||
|
||||
Attr *NewAttr =
|
||||
instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
|
||||
I->NewDecl->addAttr(NewAttr);
|
||||
|
||||
@@ -142,6 +142,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
|
||||
LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
|
||||
} else {
|
||||
// Allow 'this' within late-parsed attributes.
|
||||
NamedDecl *ND = dyn_cast<NamedDecl>(New);
|
||||
CXXRecordDecl *ThisContext =
|
||||
dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
|
||||
CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
|
||||
ND && ND->isCXXInstanceMember());
|
||||
|
||||
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
|
||||
*this, TemplateArgs);
|
||||
if (NewAttr)
|
||||
@@ -2449,7 +2456,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
|
||||
CXXRecordDecl *ThisContext = 0;
|
||||
unsigned ThisTypeQuals = 0;
|
||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
||||
ThisContext = Method->getParent();
|
||||
ThisContext = cast<CXXRecordDecl>(Owner);
|
||||
ThisTypeQuals = Method->getTypeQualifiers();
|
||||
}
|
||||
|
||||
@@ -2585,8 +2592,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
|
||||
|
||||
bool Expand = false;
|
||||
bool RetainExpansion = false;
|
||||
Optional<unsigned> NumExpansions
|
||||
= PackExpansion->getNumExpansions();
|
||||
Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
|
||||
if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
|
||||
SourceRange(),
|
||||
Unexpanded,
|
||||
|
||||
@@ -7265,18 +7265,7 @@ TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
|
||||
DeclContext *DC = getSema().getFunctionLevelDeclContext();
|
||||
QualType T;
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
|
||||
T = MD->getThisType(getSema().Context);
|
||||
else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) {
|
||||
T = getSema().Context.getPointerType(
|
||||
getSema().Context.getRecordType(Record));
|
||||
} else {
|
||||
assert(SemaRef.Context.getDiagnostics().hasErrorOccurred() &&
|
||||
"this in the wrong scope?");
|
||||
return ExprError();
|
||||
}
|
||||
QualType T = getSema().getCurrentThisType();
|
||||
|
||||
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
|
||||
// Make sure that we capture 'this'.
|
||||
|
||||
@@ -30,16 +30,44 @@ struct C {
|
||||
float &f(T*) const noexcept;
|
||||
|
||||
T* ptr;
|
||||
auto g1() noexcept(noexcept(f(ptr))) -> decltype(f((*this).ptr));
|
||||
auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(ptr));
|
||||
auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr));
|
||||
auto g3() noexcept(noexcept(f(this->ptr))) -> decltype(f((*this).ptr));
|
||||
auto g4() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(this->ptr));
|
||||
auto g5() noexcept(noexcept(this->f(ptr))) -> decltype(this->f(ptr));
|
||||
auto g6() const noexcept(noexcept(this->f(((this))->ptr))) -> decltype(this->f(ptr));
|
||||
auto g7() noexcept(noexcept(this->f(this->ptr))) -> decltype(this->f((*this).ptr));
|
||||
auto g8() const noexcept(noexcept(this->f(((this))->ptr))) -> decltype(this->f(this->ptr));
|
||||
};
|
||||
|
||||
void test_C(C<int> ci) {
|
||||
int *p = 0;
|
||||
int &ir = ci.g1();
|
||||
float &fr = ci.g2();
|
||||
int &ir2 = ci.g3();
|
||||
float &fr2 = ci.g4();
|
||||
int &ir3 = ci.g5();
|
||||
float &fr3 = ci.g6();
|
||||
int &ir4 = ci.g7();
|
||||
float &fr4 = ci.g8();
|
||||
static_assert(!noexcept(ci.g1()), "exception-specification failure");
|
||||
static_assert(noexcept(ci.g2()), "exception-specification failure");
|
||||
static_assert(!noexcept(ci.g3()), "exception-specification failure");
|
||||
static_assert(noexcept(ci.g4()), "exception-specification failure");
|
||||
static_assert(!noexcept(ci.g5()), "exception-specification failure");
|
||||
static_assert(noexcept(ci.g6()), "exception-specification failure");
|
||||
static_assert(!noexcept(ci.g7()), "exception-specification failure");
|
||||
static_assert(noexcept(ci.g8()), "exception-specification failure");
|
||||
}
|
||||
|
||||
namespace PR14263 {
|
||||
template<typename T> struct X {
|
||||
void f();
|
||||
T f() const;
|
||||
|
||||
auto g() -> decltype(this->f()) { return f(); }
|
||||
auto g() const -> decltype(this->f()) { return f(); }
|
||||
};
|
||||
template struct X<int>;
|
||||
}
|
||||
|
||||
namespace PR10036 {
|
||||
|
||||
Reference in New Issue
Block a user