]> granicus.if.org Git - clang/commitdiff
Implement transformation of nested-name-specifiers within the general
authorDouglas Gregor <dgregor@apple.com>
Thu, 6 Aug 2009 05:28:30 +0000 (05:28 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 6 Aug 2009 05:28:30 +0000 (05:28 +0000)
tree transformation. Template instantiation uses this general
transformation rather than implementing its own transformation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78286 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/TreeTransform.h

index 76296c690ccd2493b09ba98bac0b438b62b07609..7ef30d364758f419d3cd18fdc767a95e0174c139 100644 (file)
@@ -2181,8 +2181,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
       = LookupQualifiedName(DC, DeclarationName(&Member),  
                             LookupMemberName, false);
 
-    if (SS && SS->isSet())
-    {
+    if (SS && SS->isSet()) {
       QualType BaseTypeCanon 
         = Context.getCanonicalType(BaseType).getUnqualifiedType();
       QualType MemberTypeCanon 
index c281b96a9ea6c6f4c51c51cd9f08de8b3f50ee58..5f378993a254f01d11adb8447d64b228b8fda990 100644 (file)
@@ -324,10 +324,6 @@ namespace {
     /// this declaration.
     Decl *TransformDecl(Decl *D);
     
-    /// \brief Transform the given nested-name-specifier by instantiating it.
-    NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
-                                                      SourceRange Range);
-    
     /// \brief Transform the given template name by instantiating it.
     TemplateName TransformTemplateName(TemplateName Template);
     
@@ -345,12 +341,6 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) {
   return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
 }
 
-NestedNameSpecifier *
-TemplateInstantiator::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
-                                                   SourceRange Range) {
-  return getSema().InstantiateNestedNameSpecifier(NNS, Range, TemplateArgs);
-}
-
 TemplateName 
 TemplateInstantiator::TransformTemplateName(TemplateName Template) {
   return getSema().InstantiateTemplateName(Template, /*FIXME*/Loc, 
@@ -722,59 +712,9 @@ NestedNameSpecifier *
 Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
                                      SourceRange Range,
                                      const TemplateArgumentList &TemplateArgs) {
-  // Instantiate the prefix of this nested name specifier.
-  NestedNameSpecifier *Prefix = NNS->getPrefix();
-  if (Prefix) {
-    Prefix = InstantiateNestedNameSpecifier(Prefix, Range, TemplateArgs);
-    if (!Prefix)
-      return 0;
-  }
-
-  switch (NNS->getKind()) {
-  case NestedNameSpecifier::Identifier: {
-    assert(Prefix && 
-           "Can't have an identifier nested-name-specifier with no prefix");
-    CXXScopeSpec SS;
-    // FIXME: The source location information is all wrong.
-    SS.setRange(Range);
-    SS.setScopeRep(Prefix);
-    return static_cast<NestedNameSpecifier *>(
-                                 ActOnCXXNestedNameSpecifier(0, SS,
-                                                             Range.getEnd(),
-                                                             Range.getEnd(),
-                                                    *NNS->getAsIdentifier()));
-    break;
-  }
-
-  case NestedNameSpecifier::Namespace:
-  case NestedNameSpecifier::Global:
-    return NNS;
-    
-  case NestedNameSpecifier::TypeSpecWithTemplate:
-  case NestedNameSpecifier::TypeSpec: {
-    QualType T = QualType(NNS->getAsType(), 0);
-    if (!T->isDependentType())
-      return NNS;
-
-    T = InstantiateType(T, TemplateArgs, Range.getBegin(), DeclarationName());
-    if (T.isNull())
-      return 0;
-
-    if (T->isDependentType() || T->isRecordType() ||
-        (getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
-      assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
-      return NestedNameSpecifier::Create(Context, Prefix, 
-                 NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
-                                         T.getTypePtr());
-    }
-
-    Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T;
-    return 0;
-  }
-  }
-
-  // Required to silence a GCC warning
-  return 0;
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
+                                    DeclarationName());
+  return Instantiator.TransformNestedNameSpecifier(NNS, Range);
 }
 
 TemplateName
index 0aefda7f11875bac63c0566754fd54bd63cd6561..70ad317924efaf8be8653ebebedd5c55fb38b04e 100644 (file)
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_SEMA_TREETRANSFORM_H
 
 #include "Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
 #include <algorithm>
 
 namespace clang {
@@ -156,12 +157,15 @@ public:
   /// \brief Transform the given declaration, which is referenced from a type
   /// or expression.
   ///
-  /// Subclasses must override this.
-  Decl *TransformDecl(Decl *D);
+  /// By default, acts as the identity function on declarations. Subclasses
+  /// may override this function to provide alternate behavior.
+  Decl *TransformDecl(Decl *D) { return D; }
   
   /// \brief Transform the given nested-name-specifier.
   ///
-  /// Subclasses must override this.
+  /// By default, transforms all of the types and declarations within the 
+  /// nested-name-specifier. Subclasses may override this function to provide
+  /// alternate behavior.
   NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
                                                     SourceRange Range);
   
@@ -397,9 +401,97 @@ public:
                                const IdentifierInfo *Id) {
     return SemaRef.CheckTypenameType(NNS, *Id,
                                   SourceRange(getDerived().getBaseLocation()));
-  }    
+  }
+  
+  /// \brief Build a new nested-name-specifier given the prefix and an
+  /// identifier that names the next step in the nested-name-specifier.
+  ///
+  /// By default, performs semantic analysis when building the new
+  /// nested-name-specifier. Subclasses may override this routine to provide
+  /// different behavior.
+  NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                  SourceRange Range,
+                                                  IdentifierInfo &II);
+
+  /// \brief Build a new nested-name-specifier given the prefix and the
+  /// namespace named in the next step in the nested-name-specifier.
+  ///
+  /// By default, performs semantic analysis when building the new
+  /// nested-name-specifier. Subclasses may override this routine to provide
+  /// different behavior.
+  NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                  SourceRange Range,
+                                                  NamespaceDecl *NS);
+
+  /// \brief Build a new nested-name-specifier given the prefix and the
+  /// type named in the next step in the nested-name-specifier.
+  ///
+  /// By default, performs semantic analysis when building the new
+  /// nested-name-specifier. Subclasses may override this routine to provide
+  /// different behavior.
+  NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                  SourceRange Range,
+                                                  bool TemplateKW,
+                                                  QualType T);
 };
   
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                                     SourceRange Range) {
+  // Instantiate the prefix of this nested name specifier.
+  NestedNameSpecifier *Prefix = NNS->getPrefix();
+  if (Prefix) {
+    Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range);
+    if (!Prefix)
+      return 0;
+  }
+  
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    assert(Prefix && 
+           "Can't have an identifier nested-name-specifier with no prefix");
+    if (!getDerived().AlwaysRebuild() && Prefix == NNS->getPrefix())
+      return NNS;
+      
+    return getDerived().RebuildNestedNameSpecifier(Prefix, Range, 
+                                                   *NNS->getAsIdentifier());
+      
+  case NestedNameSpecifier::Namespace: {
+    NamespaceDecl *NS 
+      = cast_or_null<NamespaceDecl>(
+                            getDerived().TransformDecl(NNS->getAsNamespace()));
+    if (!getDerived().AlwaysRebuild() && 
+        Prefix == NNS->getPrefix() &&
+        NS == NNS->getAsNamespace())
+      return NNS;
+    
+    return getDerived().RebuildNestedNameSpecifier(Prefix, Range, NS);
+  }
+      
+  case NestedNameSpecifier::Global:
+    // There is no meaningful transformation that one could perform on the
+    // global scope.
+    return NNS;
+      
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec: {
+    QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+    if (!getDerived().AlwaysRebuild() &&
+        Prefix == NNS->getPrefix() &&
+        T == QualType(NNS->getAsType(), 0))
+      return NNS;
+    
+    return getDerived().RebuildNestedNameSpecifier(Prefix, Range, 
+                  NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,    
+                                                   T);
+  }
+  }
+  
+  // Required to silence a GCC warning
+  return 0;  
+}
+
 template<typename Derived>
 TemplateArgument 
 TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
@@ -1212,6 +1304,45 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
                                      SourceLocation());  
 }
   
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   IdentifierInfo &II) {
+  CXXScopeSpec SS;
+  // FIXME: The source location information is all wrong.
+  SS.setRange(Range);
+  SS.setScopeRep(Prefix);
+  return static_cast<NestedNameSpecifier *>(
+                    SemaRef.ActOnCXXNestedNameSpecifier(0, SS, Range.getEnd(), 
+                                                        Range.getEnd(), II));
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   NamespaceDecl *NS) {
+  return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS);
+}
+
+template<typename Derived>
+NestedNameSpecifier *
+TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
+                                                   SourceRange Range,
+                                                   bool TemplateKW,
+                                                   QualType T) {
+  if (T->isDependentType() || T->isRecordType() ||
+      (SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
+    assert(T.getCVRQualifiers() == 0 && "Can't get cv-qualifiers here");
+    return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,
+                                       T.getTypePtr());
+  }
+  
+  SemaRef.Diag(Range.getBegin(), diag::err_nested_name_spec_non_tag) << T;
+  return 0;
+}
+  
 } // end namespace clang
 
 #endif // LLVM_CLANG_SEMA_TREETRANSFORM_H