aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Type.h5
-rw-r--r--lib/AST/ExprCXX.cpp16
-rw-r--r--lib/AST/Type.cpp10
-rw-r--r--lib/Sema/SemaExpr.cpp24
-rw-r--r--lib/Sema/TreeTransform.h37
5 files changed, 57 insertions, 35 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 5f5377414d..7eb332bd95 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -923,6 +923,11 @@ public:
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.
//
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 5f908096bb..c394e476f8 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -728,15 +728,15 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
// 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>();
@@ -744,11 +744,11 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
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() {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 52ee60b984..05e7fdc49e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -415,6 +415,16 @@ const CXXRecordDecl *Type::getCXXRecordDeclForPointerType() const {
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 &&
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 088ca96edd..997b8f8dcb 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1063,6 +1063,15 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
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);
@@ -3231,6 +3240,21 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
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);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 2f36807659..cca14caa44 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -5336,19 +5336,16 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
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);
}
@@ -5735,7 +5732,6 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
BaseType = getDerived().TransformType(Old->getBaseType());
}
- CXXRecordDecl *NamingClass = 0;
NestedNameSpecifier *Qualifier = 0;
if (Old->getQualifier()) {
Qualifier
@@ -5743,12 +5739,6 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
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(),
@@ -5783,24 +5773,17 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
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()) {