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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102448
91177308-0d34-0410-b5e6-
96231b3b80d8
const ObjCInterfaceType *getAsObjCQualifiedInterfaceType() const;
const CXXRecordDecl *getCXXRecordDeclForPointerType() const;
+ /// \brief Retrieves the CXXRecordDecl that this type refers to, either
+ /// because the type is a RecordType or because it is the injected-class-name
+ /// type of a class template or class template partial specialization.
+ CXXRecordDecl *getAsCXXRecordDecl() const;
+
// Member-template getAs<specific type>'. This scheme will eventually
// replace the specific getAsXXXX methods above.
//
// If there was a nested name specifier, it names the naming class.
// It can't be dependent: after all, we were actually able to do the
// lookup.
- const RecordType *RT;
+ CXXRecordDecl *Record = 0;
if (getQualifier()) {
Type *T = getQualifier()->getAsType();
assert(T && "qualifier in member expression does not name type");
- RT = T->getAs<RecordType>();
- assert(RT && "qualifier in member expression does not name record");
-
+ Record = T->getAsCXXRecordDecl();
+ assert(Record && "qualifier in member expression does not name record");
+ }
// Otherwise the naming class must have been the base class.
- } else {
+ else {
QualType BaseType = getBaseType().getNonReferenceType();
if (isArrow()) {
const PointerType *PT = BaseType->getAs<PointerType>();
BaseType = PT->getPointeeType();
}
- RT = BaseType->getAs<RecordType>();
- assert(RT && "base of member expression does not name record");
+ Record = BaseType->getAsCXXRecordDecl();
+ assert(Record && "base of member expression does not name record");
}
- return cast<CXXRecordDecl>(RT->getDecl());
+ return Record;
}
Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
return 0;
}
+CXXRecordDecl *Type::getAsCXXRecordDecl() const {
+ if (const RecordType *RT = getAs<RecordType>())
+ return dyn_cast<CXXRecordDecl>(RT->getDecl());
+ else if (const InjectedClassNameType *Injected
+ = getAs<InjectedClassNameType>())
+ return Injected->getDecl();
+
+ return 0;
+}
+
bool Type::isIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
if (TemplateArgs) {
// Just re-use the lookup done by isTemplateName.
DecomposeTemplateName(R, Id);
+
+ // Re-derive the naming class.
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (const Type *Ty = Qualifier->getAsType())
+ if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
+ R.setNamingClass(NamingClass);
+ }
} else {
bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
if (TemplateArgs) {
// Re-use the lookup done for the template name.
DecomposeTemplateName(R, Id);
+
+ // Re-derive the naming class.
+ if (SS.isSet()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ if (const Type *Ty = Qualifier->getAsType())
+ if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl())
+ R.setNamingClass(NamingClass);
+ } else {
+ QualType BaseType = Base->getType();
+ if (const PointerType *Ptr = BaseType->getAs<PointerType>())
+ BaseType = Ptr->getPointeeType();
+ if (CXXRecordDecl *NamingClass = BaseType->getAsCXXRecordDecl())
+ R.setNamingClass(NamingClass);
+ }
} else {
Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
SS, ObjCImpDecl);
SS.setScopeRep(Qualifier);
SS.setRange(Old->getQualifierRange());
-
- // If this nested-name-specifier refers to a class type, that is the
- // naming class.
- if (const Type *NamedType = Qualifier->getAsType())
- if (const RecordType *NamedRecord = NamedType->getAs<RecordType>())
- R.setNamingClass(cast<CXXRecordDecl>(NamedRecord->getDecl()));
- } else if (Old->getNamingClass()) {
+ }
+
+ if (Old->getNamingClass()) {
CXXRecordDecl *NamingClass
= cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
Old->getNameLoc(),
Old->getNamingClass()));
if (!NamingClass)
return SemaRef.ExprError();
+
R.setNamingClass(NamingClass);
}
BaseType = getDerived().TransformType(Old->getBaseType());
}
- CXXRecordDecl *NamingClass = 0;
NestedNameSpecifier *Qualifier = 0;
if (Old->getQualifier()) {
Qualifier
Old->getQualifierRange());
if (Qualifier == 0)
return SemaRef.ExprError();
-
- // If this nested-name-specifier refers to a class type, that is the
- // naming class.
- if (const Type *NamedType = Qualifier->getAsType())
- if (const RecordType *NamedRecord = NamedType->getAs<RecordType>())
- NamingClass = cast<CXXRecordDecl>(NamedRecord->getDecl());
}
LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
R.resolveKind();
- // Determine the naming class, if we haven't already.
- if (!NamingClass) {
- QualType T = BaseType;
- if (const PointerType *PointerTy = T->getAs<PointerType>())
- T = PointerTy->getPointeeType();
- if (const RecordType *NamedRecord = T->getAs<RecordType>())
- NamingClass = cast<CXXRecordDecl>(NamedRecord->getDecl());
- }
-
- if (!NamingClass && Old->getNamingClass()) {
- NamingClass = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
+ // Determine the naming class.
+ if (!Old->getNamingClass()) {
+ CXXRecordDecl *NamingClass
+ = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl(
Old->getMemberLoc(),
Old->getNamingClass()));
if (!NamingClass)
return SemaRef.ExprError();
- }
- if (NamingClass)
+
R.setNamingClass(NamingClass);
+ }
TemplateArgumentListInfo TransArgs;
if (Old->hasExplicitTemplateArgs()) {