Skip to content

Commit 9262f47

Browse files
committed
During template instantiation, set the naming class of
UnresolvedLookupExpr and UnresolvedMemberExpr by substituting the naming class we computed when building the expression in the template... ... which we didn't always do correctly. Teach UnresolvedMemberExpr::getNamingClass() all about the new representation of injected-class-names in templates, so that it can return a naming class that is the current instantiation. Also, when decomposing a template-id into its template name and its arguments, be sure to set the naming class on the LookupResult structure. Fixes PR6947 the right way. llvm-svn: 102448
1 parent 0a3fe04 commit 9262f47

File tree

5 files changed

+57
-35
lines changed

5 files changed

+57
-35
lines changed

clang/include/clang/AST/Type.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,11 @@ class Type {
923923
const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const;
924924
const CXXRecordDecl *getCXXRecordDeclForPointerType() const;
925925

926+
/// \brief Retrieves the CXXRecordDecl that this type refers to, either
927+
/// because the type is a RecordType or because it is the injected-class-name
928+
/// type of a class template or class template partial specialization.
929+
CXXRecordDecl *getAsCXXRecordDecl() const;
930+
926931
// Member-template getAs<specific type>'. This scheme will eventually
927932
// replace the specific getAsXXXX methods above.
928933
//

clang/lib/AST/ExprCXX.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -728,27 +728,27 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
728728
// If there was a nested name specifier, it names the naming class.
729729
// It can't be dependent: after all, we were actually able to do the
730730
// lookup.
731-
const RecordType *RT;
731+
CXXRecordDecl *Record = 0;
732732
if (getQualifier()) {
733733
Type *T = getQualifier()->getAsType();
734734
assert(T && "qualifier in member expression does not name type");
735-
RT = T->getAs<RecordType>();
736-
assert(RT && "qualifier in member expression does not name record");
737-
735+
Record = T->getAsCXXRecordDecl();
736+
assert(Record && "qualifier in member expression does not name record");
737+
}
738738
// Otherwise the naming class must have been the base class.
739-
} else {
739+
else {
740740
QualType BaseType = getBaseType().getNonReferenceType();
741741
if (isArrow()) {
742742
const PointerType *PT = BaseType->getAs<PointerType>();
743743
assert(PT && "base of arrow member access is not pointer");
744744
BaseType = PT->getPointeeType();
745745
}
746746

747-
RT = BaseType->getAs<RecordType>();
748-
assert(RT && "base of member expression does not name record");
747+
Record = BaseType->getAsCXXRecordDecl();
748+
assert(Record && "base of member expression does not name record");
749749
}
750750

751-
return cast<CXXRecordDecl>(RT->getDecl());
751+
return Record;
752752
}
753753

754754
Stmt::child_iterator UnresolvedMemberExpr::child_begin() {

clang/lib/AST/Type.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,16 @@ const CXXRecordDecl *Type::getCXXRecordDeclForPointerType() const {
415415
return 0;
416416
}
417417

418+
CXXRecordDecl *Type::getAsCXXRecordDecl() const {
419+
if (const RecordType *RT = getAs<RecordType>())
420+
return dyn_cast<CXXRecordDecl>(RT->getDecl());
421+
else if (const InjectedClassNameType *Injected
422+
= getAs<InjectedClassNameType>())
423+
return Injected->getDecl();
424+
425+
return 0;
426+
}
427+
418428
bool Type::isIntegerType() const {
419429
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
420430
return BT->getKind() >= BuiltinType::Bool &&

clang/lib/Sema/SemaExpr.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,15 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
10631063
if (TemplateArgs) {
10641064
// Just re-use the lookup done by isTemplateName.
10651065
DecomposeTemplateName(R, Id);
1066+
1067+
// Re-derive the naming class.
1068+
if (SS.isSet()) {
1069+
NestedNameSpecifier *Qualifier
1070+
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
1071+
if (const Type *Ty = Qualifier->getAsType())
1072+
if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
1073+
R.setNamingClass(NamingClass);
1074+
}
10661075
} else {
10671076
bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
10681077
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
@@ -3231,6 +3240,21 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
32313240
if (TemplateArgs) {
32323241
// Re-use the lookup done for the template name.
32333242
DecomposeTemplateName(R, Id);
3243+
3244+
// Re-derive the naming class.
3245+
if (SS.isSet()) {
3246+
NestedNameSpecifier *Qualifier
3247+
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
3248+
if (const Type *Ty = Qualifier->getAsType())
3249+
if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
3250+
R.setNamingClass(NamingClass);
3251+
} else {
3252+
QualType BaseType = Base->getType();
3253+
if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3254+
BaseType = Ptr->getPointeeType();
3255+
if (CXXRecordDecl *NamingClass = BaseType->getAsCXXRecordDecl())
3256+
R.setNamingClass(NamingClass);
3257+
}
32343258
} else {
32353259
Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
32363260
SS, ObjCImpDecl);

clang/lib/Sema/TreeTransform.h

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5336,19 +5336,16 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
53365336

53375337
SS.setScopeRep(Qualifier);
53385338
SS.setRange(Old->getQualifierRange());
5339-
5340-
// If this nested-name-specifier refers to a class type, that is the
5341-
// naming class.
5342-
if (const Type *NamedType = Qualifier->getAsType())
5343-
if (const RecordType *NamedRecord = NamedType->getAs<RecordType>())
5344-
R.setNamingClass(cast<CXXRecordDecl>(NamedRecord->getDecl()));
5345-
} else if (Old->getNamingClass()) {
5339+
}
5340+
5341+
if (Old->getNamingClass()) {
53465342
CXXRecordDecl *NamingClass
53475343
= cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
53485344
Old->getNameLoc(),
53495345
Old->getNamingClass()));
53505346
if (!NamingClass)
53515347
return SemaRef.ExprError();
5348+
53525349
R.setNamingClass(NamingClass);
53535350
}
53545351

@@ -5735,20 +5732,13 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
57355732
BaseType = getDerived().TransformType(Old->getBaseType());
57365733
}
57375734

5738-
CXXRecordDecl *NamingClass = 0;
57395735
NestedNameSpecifier *Qualifier = 0;
57405736
if (Old->getQualifier()) {
57415737
Qualifier
57425738
= getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
57435739
Old->getQualifierRange());
57445740
if (Qualifier == 0)
57455741
return SemaRef.ExprError();
5746-
5747-
// If this nested-name-specifier refers to a class type, that is the
5748-
// naming class.
5749-
if (const Type *NamedType = Qualifier->getAsType())
5750-
if (const RecordType *NamedRecord = NamedType->getAs<RecordType>())
5751-
NamingClass = cast<CXXRecordDecl>(NamedRecord->getDecl());
57525742
}
57535743

57545744
LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
@@ -5783,24 +5773,17 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
57835773

57845774
R.resolveKind();
57855775

5786-
// Determine the naming class, if we haven't already.
5787-
if (!NamingClass) {
5788-
QualType T = BaseType;
5789-
if (const PointerType *PointerTy = T->getAs<PointerType>())
5790-
T = PointerTy->getPointeeType();
5791-
if (const RecordType *NamedRecord = T->getAs<RecordType>())
5792-
NamingClass = cast<CXXRecordDecl>(NamedRecord->getDecl());
5793-
}
5794-
5795-
if (!NamingClass && Old->getNamingClass()) {
5796-
NamingClass = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
5776+
// Determine the naming class.
5777+
if (!Old->getNamingClass()) {
5778+
CXXRecordDecl *NamingClass
5779+
= cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
57975780
Old->getMemberLoc(),
57985781
Old->getNamingClass()));
57995782
if (!NamingClass)
58005783
return SemaRef.ExprError();
5801-
}
5802-
if (NamingClass)
5784+
58035785
R.setNamingClass(NamingClass);
5786+
}
58045787

58055788
TemplateArgumentListInfo TransArgs;
58065789
if (Old->hasExplicitTemplateArgs()) {

0 commit comments

Comments
 (0)