/// instantiating it.
Decl *TransformDefinition(Decl *D);
+ /// \bried Transform the first qualifier within a scope by instantiating the
+ /// declaration.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
+
/// \brief Rebuild the exception declaration and register the declaration
/// as an instantiated local.
VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T,
return Inst;
}
+NamedDecl *
+TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,
+ SourceLocation Loc) {
+ // If the first part of the nested-name-specifier was a template type
+ // parameter, instantiate that type parameter down to a tag type.
+ if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) {
+ const TemplateTypeParmType *TTP
+ = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD));
+ if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType();
+ if (T.isNull())
+ return cast_or_null<NamedDecl>(TransformDecl(D));
+
+ if (const TagType *Tag = T->getAs<TagType>())
+ return Tag->getDecl();
+
+ // The resulting type is not a tag; complain.
+ getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T;
+ return 0;
+ }
+ }
+
+ return cast_or_null<NamedDecl>(TransformDecl(D));
+}
+
VarDecl *
TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,
QualType T,
/// Subclasses may override this function to provide alternate behavior.
Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); }
+ /// \brief Transform the given declaration, which was the first part of a
+ /// nested-name-specifier in a member access expression.
+ ///
+ /// This specific declaration transformation only applies to the first
+ /// identifier in a nested-name-specifier of a member access expression, e.g.,
+ /// the \c T in \c x->T::member
+ ///
+ /// By default, invokes TransformDecl() to transform the declaration.
+ /// Subclasses may override this function to provide alternate behavior.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) {
+ return cast_or_null<NamedDecl>(getDerived().TransformDecl(D));
+ }
+
/// \brief Transform the given nested-name-specifier.
///
/// By default, transforms all of the types and declarations within the
if (Base.isInvalid())
return SemaRef.ExprError();
+ // Start the member reference and compute the object's type.
Sema::TypeTy *ObjectType = 0;
Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
E->getOperatorLoc(),
if (Base.isInvalid())
return SemaRef.ExprError();
- // FIXME: The first qualifier found might be a template type parameter,
- // in which case there is no transformed declaration to refer to (it might
- // refer to a built-in type!).
+ // Transform the first part of the nested-name-specifier that qualifies
+ // the member name.
NamedDecl *FirstQualifierInScope
- = cast_or_null<NamedDecl>(
- getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
+ = getDerived().TransformFirstQualifierInScope(
+ E->getFirstQualifierFoundInScope(),
+ E->getQualifierRange().getBegin());
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {