]> granicus.if.org Git - clang/commitdiff
During template instantiation, set the naming class of
authorDouglas Gregor <dgregor@apple.com>
Tue, 27 Apr 2010 18:19:34 +0000 (18:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 27 Apr 2010 18:19:34 +0000 (18:19 +0000)
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

include/clang/AST/Type.h
lib/AST/ExprCXX.cpp
lib/AST/Type.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/TreeTransform.h

index 5f5377414d980da47e827c82fd5c56647c826de7..7eb332bd95ae17d3e5a6b0611f6ccb2775a9ea4c 100644 (file)
@@ -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.
   //
index 5f908096bbb0ccd16f318e7f266ff55c0f899fc1..c394e476f81c450f98e50f70f89b66bcb9742124 100644 (file)
@@ -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() {
index 52ee60b984ec1b357109d194a6e483d03b35d858..05e7fdc49e3547d2c5d2da007eabd48223085a4a 100644 (file)
@@ -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 &&
index 088ca96edd61ca6bace11284b077457aef4a3b6e..997b8f8dcb182902ab13541f2a5cb7bfc3609fb7 100644 (file)
@@ -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);
index 2f36807659c5e80536ad5e9f3b6a2669ebeb601f..cca14caa4439a2e817077522b7b07e81d2dec8bf 100644 (file)
@@ -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()) {