From: Douglas Gregor Date: Thu, 6 Aug 2009 05:28:30 +0000 (+0000) Subject: Implement transformation of nested-name-specifiers within the general X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dcee1a12c83a6cbc9b5bf42df5d4efbc502664e7;p=clang Implement transformation of nested-name-specifiers within the general 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 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 76296c690c..7ef30d3647 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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 diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c281b96a9e..5f378993a2 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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(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( - 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 diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 0aefda7f11..70ad317924 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_SEMA_TREETRANSFORM_H #include "Sema.h" +#include "clang/Sema/SemaDiagnostic.h" #include 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 +NestedNameSpecifier * +TreeTransform::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( + 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 TemplateArgument TreeTransform::TransformTemplateArgument(const TemplateArgument &Arg) { @@ -1212,6 +1304,45 @@ QualType TreeTransform::RebuildTemplateSpecializationType( SourceLocation()); } +template +NestedNameSpecifier * +TreeTransform::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( + SemaRef.ActOnCXXNestedNameSpecifier(0, SS, Range.getEnd(), + Range.getEnd(), II)); +} + +template +NestedNameSpecifier * +TreeTransform::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix, + SourceRange Range, + NamespaceDecl *NS) { + return NestedNameSpecifier::Create(SemaRef.Context, Prefix, NS); +} + +template +NestedNameSpecifier * +TreeTransform::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