diff options
author | John McCall <rjmccall@apple.com> | 2009-09-11 04:59:25 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-09-11 04:59:25 +0000 |
commit | c4e7019d5c9034a2d84ee4695f8e98dc025ac131 (patch) | |
tree | da8b19b3e6e6f62ddc50db7209b8dd0421fd15a8 /lib/Sema | |
parent | 66847a2826c97b8e09aec304a0a7b4fe1dc35969 (diff) |
Support elaborated dependent types and diagnose tag mismatches.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81504 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 32 |
4 files changed, 80 insertions, 5 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index dc41aba094..b17e54ebe3 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -609,7 +609,15 @@ public: IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl); + bool &OwnedDecl, bool &IsDependent); + + virtual TypeResult ActOnDependentTag(Scope *S, + unsigned TagSpec, + TagUseKind TUK, + const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation TagLoc, + SourceLocation NameLoc); virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, IdentifierInfo *ClassName, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 65516f2c29..53fab18017 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3988,7 +3988,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, AccessSpecifier AS, MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl) { + bool &OwnedDecl, bool &IsDependent) { // If this is not a definition, it must have a name. assert((Name != 0 || TUK == TUK_Definition) && "Nameless record must be a definition!"); @@ -4034,6 +4034,16 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, goto CreateNewDecl; } + // If this is a friend or a reference to a class in a dependent + // context, don't try to make a decl for it. + if (TUK == TUK_Friend || TUK == TUK_Reference) { + DC = computeDeclContext(SS, false); + if (!DC) { + IsDependent = true; + return DeclPtrTy(); + } + } + if (RequireCompleteDeclContext(SS)) return DeclPtrTy::make((Decl *)0); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index fceac854ee..63c29de82b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1159,9 +1159,10 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) { Diag(TagLoc, diag::err_use_with_wrong_tag) - << Id + << Type << CodeModificationHint::CreateReplacement(SourceRange(TagLoc), D->getKindName()); + Diag(D->getLocation(), diag::note_previous_use); } } @@ -3058,9 +3059,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, AttributeList *Attr) { bool Owned = false; + bool IsDependent = false; DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TUK_Reference, KWLoc, SS, Name, NameLoc, Attr, AS_none, - MultiTemplateParamsArg(*this, 0, 0), Owned); + MultiTemplateParamsArg(*this, 0, 0), + Owned, IsDependent); + assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); + if (!TagD) return true; @@ -3124,6 +3129,28 @@ Sema::ActOnExplicitInstantiation(Scope *S, } Sema::TypeResult +Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + const CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation TagLoc, SourceLocation NameLoc) { + // This has to hold, because SS is expected to be defined. + assert(Name && "Expected a name in a dependent tag"); + + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + if (!NNS) + return true; + + QualType T = CheckTypenameType(NNS, *Name, SourceRange(TagLoc, NameLoc)); + if (T.isNull()) + return true; + + TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec); + QualType ElabType = Context.getElaboratedType(T, TagKind); + + return ElabType.getAsOpaquePtr(); +} + +Sema::TypeResult Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc) { NestedNameSpecifier *NNS diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 651d4a50dc..e719bbde92 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -391,6 +391,10 @@ namespace { IdentifierInfo *Name, SourceLocation Loc, SourceRange TypeRange); + /// \brief Check for tag mismatches when instantiating an + /// elaborated type. + QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag); + Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E); Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E); @@ -451,7 +455,33 @@ TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl, return Var; } -Sema::OwningExprResult +QualType +TemplateInstantiator::RebuildElaboratedType(QualType T, + ElaboratedType::TagKind Tag) { + if (const TagType *TT = T->getAs<TagType>()) { + TagDecl* TD = TT->getDecl(); + + // FIXME: this location is very wrong; we really need typelocs. + SourceLocation TagLocation = TD->getTagKeywordLoc(); + + // FIXME: type might be anonymous. + IdentifierInfo *Id = TD->getIdentifier(); + + // TODO: should we even warn on struct/class mismatches for this? Seems + // like it's likely to produce a lot of spurious errors. + if (!SemaRef.isAcceptableTagRedeclaration(TD, Tag, TagLocation, *Id)) { + SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag) + << Id + << CodeModificationHint::CreateReplacement(SourceRange(TagLocation), + TD->getKindName()); + SemaRef.Diag(TD->getLocation(), diag::note_previous_use); + } + } + + return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(T, Tag); +} + +Sema::OwningExprResult TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { if (!E->isTypeDependent()) return SemaRef.Owned(E->Retain()); |