diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 46 | ||||
-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 |
6 files changed, 107 insertions, 28 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 5d62c0c67e..f08c481c52 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1641,10 +1641,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, else TUK = Action::TUK_Reference; bool Owned = false; + bool IsDependent = false; DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, Attr, AS, Action::MultiTemplateParamsArg(Actions), - Owned); + Owned, IsDependent); + assert(!IsDependent && "didn't expect dependent enum"); if (Tok.is(tok::l_brace)) ParseEnumBody(StartLoc, TagDecl); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index fc3e6ae17f..8fa8525750 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -619,7 +619,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } // Create the tag portion of the class or class template. - Action::DeclResult TagOrTempResult; + Action::DeclResult TagOrTempResult = true; // invalid + Action::TypeResult TypeResult = true; // invalid TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; // FIXME: When TUK == TUK_Reference and we have a template-id, we need @@ -651,7 +652,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->RAngleLoc, Attr); } else if (TUK == Action::TUK_Reference || TUK == Action::TUK_Friend) { - Action::TypeResult Type + TypeResult = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template), TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, @@ -659,23 +660,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateId->getTemplateArgLocations(), TemplateId->RAngleLoc); - Type = Actions.ActOnTagTemplateIdType(Type, TUK, TagType, StartLoc); - - TemplateId->Destroy(); - - if (Type.isInvalid()) { - DS.SetTypeSpecError(); - return; - } - - const char *PrevSpec = 0; - unsigned DiagID; - if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, PrevSpec, - DiagID, Type.get())) - Diag(StartLoc, DiagID) << PrevSpec; - - return; - + TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK, + TagType, StartLoc); } else { // This is an explicit specialization or a class template // partial specialization. @@ -746,13 +732,21 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // FIXME: Diagnose this particular error. } + bool IsDependent = false; + // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS, Name, NameLoc, Attr, AS, Action::MultiTemplateParamsArg(Actions, TemplateParams? &(*TemplateParams)[0] : 0, TemplateParams? TemplateParams->size() : 0), - Owned); + Owned, IsDependent); + + // If ActOnTag said the type was dependent, try again with the + // less common call. + if (IsDependent) + TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK, + SS, Name, StartLoc, NameLoc); } // Parse the optional base clause (C++ only). @@ -771,15 +765,23 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Diag(Tok, diag::err_expected_lbrace); } - if (TagOrTempResult.isInvalid()) { + void *Result; + if (!TypeResult.isInvalid()) { + TagType = DeclSpec::TST_typename; + Result = TypeResult.get(); + Owned = false; + } else if (!TagOrTempResult.isInvalid()) { + Result = TagOrTempResult.get().getAs<void>(); + } else { DS.SetTypeSpecError(); return; } const char *PrevSpec = 0; unsigned DiagID; + if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, DiagID, - TagOrTempResult.get().getAs<void>(), Owned)) + Result, Owned)) Diag(StartLoc, DiagID) << PrevSpec; } 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()); |