diff options
author | Abramo Bagnara <abramo.bagnara@gmail.com> | 2010-06-12 07:44:57 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo.bagnara@gmail.com> | 2010-06-12 07:44:57 +0000 |
commit | c98971d5c994caed9452aeadd0122c855e0f4de1 (patch) | |
tree | 6465ad4404d94124cf6166702cda75302136bf49 | |
parent | 5af93efc01f4acd247aa6d3124db6c92c3679198 (diff) |
Don't omit class explicit instantiation from AST.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105880 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 43 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 119 |
3 files changed, 110 insertions, 56 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index dc5d49b5c5..b977e298be 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -901,9 +901,22 @@ class ClassTemplateSpecializationDecl llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - /// \brief The type-as-written of an explicit template specialization. + /// \brief Further info for explicit template specialization/instantiation. + struct ExplicitSpecializationInfo { + /// \brief The type-as-written. + TypeSourceInfo *TypeAsWritten; + /// \brief The location of the extern keyword. + SourceLocation ExternLoc; + /// \brief The location of the template keyword. + SourceLocation TemplateKeywordLoc; + + ExplicitSpecializationInfo() + : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {} + }; + + /// \brief Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - TypeSourceInfo *TypeAsWritten; + ExplicitSpecializationInfo *ExplicitInfo; /// \brief The template arguments used to describe this specialization. TemplateArgumentList TemplateArgs; @@ -1018,13 +1031,33 @@ public: /// \brief Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. void setTypeAsWritten(TypeSourceInfo *T) { - TypeAsWritten = T; + if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = T; } - /// \brief Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { - return TypeAsWritten; + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0; + } + + /// \brief Gets the location of the extern keyword, if present. + SourceLocation getExternLoc() const { + return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + } + /// \brief Sets the location of the extern keyword. + void setExternLoc(SourceLocation Loc) { + if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + ExplicitInfo->ExternLoc = Loc; + } + + /// \brief Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc) { + if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + ExplicitInfo->TemplateKeywordLoc = Loc; + } + /// \brief Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } void Profile(llvm::FoldingSetNodeID &ID) const { diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 67bb55421d..85b7960075 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -426,7 +426,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), - TypeAsWritten(0), + ExplicitInfo(0), TemplateArgs(Context, Builder, /*TakeArgs=*/true), SpecializationKind(TSK_Undeclared) { } @@ -449,6 +449,8 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, } void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) { + delete ExplicitInfo; + if (SpecializedPartialSpecialization *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) C.Deallocate(PartialSpec); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5208f28ca6..44e3a40245 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3981,8 +3981,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, TemplateArgs, CanonType); - if (TUK != TUK_Friend) + if (TUK != TUK_Friend) { Specialization->setTypeAsWritten(WrittenTy); + Specialization->setTemplateKeywordLoc(KWLoc); + } TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: @@ -4076,7 +4078,7 @@ static void StripImplicitInstantiation(NamedDecl *D) { /// \param PrevPointOfInstantiation if valid, indicates where the previus /// declaration was instantiated (either implicitly or explicitly). /// -/// \param SuppressNew will be set to true to indicate that the new +/// \param HasNoEffect will be set to true to indicate that the new /// specialization or instantiation has no effect and should be ignored. /// /// \returns true if there was an error that should prevent the introduction of @@ -4087,8 +4089,8 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK, SourceLocation PrevPointOfInstantiation, - bool &SuppressNew) { - SuppressNew = false; + bool &HasNoEffect) { + HasNoEffect = false; switch (NewTSK) { case TSK_Undeclared: @@ -4145,7 +4147,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, switch (PrevTSK) { case TSK_ExplicitInstantiationDeclaration: // This explicit instantiation declaration is redundant (that's okay). - SuppressNew = true; + HasNoEffect = true; return false; case TSK_Undeclared: @@ -4160,7 +4162,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // of a template appears after a declaration of an explicit // specialization for that template, the explicit instantiation has no // effect. - SuppressNew = true; + HasNoEffect = true; return false; case TSK_ExplicitInstantiationDefinition: @@ -4174,7 +4176,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, diag::note_explicit_instantiation_definition_here); assert(PrevPointOfInstantiation.isValid() && "Explicit instantiation without point of instantiation?"); - SuppressNew = true; + HasNoEffect = true; return false; } break; @@ -4203,7 +4205,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, Diag(PrevDecl->getLocation(), diag::note_previous_template_specialization); } - SuppressNew = true; + HasNoEffect = true; return false; case TSK_ExplicitInstantiationDeclaration: @@ -4220,7 +4222,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, << PrevDecl; Diag(PrevPointOfInstantiation, diag::note_previous_explicit_instantiation); - SuppressNew = true; + HasNoEffect = true; return false; } break; @@ -4369,14 +4371,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, = Specialization->getTemplateSpecializationInfo(); assert(SpecInfo && "Function template specialization info missing?"); - bool SuppressNew = false; + bool HasNoEffect = false; if (!isFriend && CheckSpecializationInstantiationRedecl(FD->getLocation(), TSK_ExplicitSpecialization, Specialization, SpecInfo->getTemplateSpecializationKind(), SpecInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; // Mark the prior declaration as an explicit specialization, so that later @@ -4503,13 +4505,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { // use occurs; no diagnostic is required. assert(MSInfo && "Member specialization info missing?"); - bool SuppressNew = false; + bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(Member->getLocation(), TSK_ExplicitSpecialization, Instantiation, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; // Check the scope of this explicit specialization. @@ -4711,6 +4713,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + TemplateSpecializationKind PrevDecl_TSK + = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; + // C++0x [temp.explicit]p2: // [...] An explicit instantiation shall appear in an enclosing // namespace of its template. [...] @@ -4722,31 +4727,31 @@ Sema::ActOnExplicitInstantiation(Scope *S, ClassTemplateSpecializationDecl *Specialization = 0; bool ReusedDecl = false; + bool HasNoEffect = false; if (PrevDecl) { - bool SuppressNew = false; if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK, - PrevDecl, - PrevDecl->getSpecializationKind(), + PrevDecl, PrevDecl_TSK, PrevDecl->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return DeclPtrTy::make(PrevDecl); - if (SuppressNew) - return DeclPtrTy::make(PrevDecl); - - if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation || - PrevDecl->getSpecializationKind() == TSK_Undeclared) { + // Even though HasNoEffect == true means that this explicit instantiation + // has no effect on semantics, we go on to put its syntax in the AST. + + if (PrevDecl_TSK == TSK_ImplicitInstantiation || + PrevDecl_TSK == TSK_Undeclared) { // Since the only prior class template specialization with these // arguments was referenced but not declared, reuse that - // declaration node as our own, updating its source location to - // reflect our new declaration. + // declaration node as our own, updating the source location + // for the template name to reflect our new declaration. + // (Other source locations will be updated later.) Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); PrevDecl = 0; ReusedDecl = true; } } - + if (!Specialization) { // Create a new class template specialization declaration node for // this explicit specialization. @@ -4758,15 +4763,16 @@ Sema::ActOnExplicitInstantiation(Scope *S, Converted, PrevDecl); SetNestedNameSpecifier(Specialization, SS); - if (PrevDecl) { - // Remove the previous declaration from the folding set, since we want - // to introduce a new declaration. - ClassTemplate->getSpecializations().RemoveNode(PrevDecl); - ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); - } - - // Insert the new specialization. - ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); + if (!HasNoEffect) { + if (PrevDecl) { + // Remove the previous declaration from the folding set, since we want + // to introduce a new declaration. + ClassTemplate->getSpecializations().RemoveNode(PrevDecl); + ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + } + // Insert the new specialization. + ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); + } } // Build the fully-sugared type for this explicit instantiation as @@ -4783,12 +4789,21 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); - if (!ReusedDecl) { - // Add the explicit instantiation into its lexical context. However, - // since explicit instantiations are never found by name lookup, we - // just put it into the declaration context directly. - Specialization->setLexicalDeclContext(CurContext); - CurContext->addDecl(Specialization); + // Set source locations for keywords. + Specialization->setExternLoc(ExternLoc); + Specialization->setTemplateKeywordLoc(TemplateLoc); + + // Add the explicit instantiation into its lexical context. However, + // since explicit instantiations are never found by name lookup, we + // just put it into the declaration context directly. + Specialization->setLexicalDeclContext(CurContext); + CurContext->addDecl(Specialization); + + // Syntax is now OK, so return if it has no other effect on semantics. + if (HasNoEffect) { + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); + return DeclPtrTy::make(Specialization); } // C++ [temp.explicit]p3: @@ -4803,8 +4818,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->getDefinition()); if (!Def) InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK); - else if (TSK == TSK_ExplicitInstantiationDefinition) + else if (TSK == TSK_ExplicitInstantiationDefinition) { MarkVTableUsed(TemplateNameLoc, Specialization, true); + Specialization->setPointOfInstantiation(Def->getPointOfInstantiation()); + } // Instantiate the members of this class template specialization. Def = cast_or_null<ClassTemplateSpecializationDecl>( @@ -4821,6 +4838,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); } + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); return DeclPtrTy::make(Specialization); } @@ -4898,15 +4917,15 @@ Sema::ActOnExplicitInstantiation(Scope *S, PrevDecl = Record; if (PrevDecl) { MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo(); - bool SuppressNew = false; + bool HasNoEffect = false; assert(MSInfo && "No member specialization information?"); if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK, PrevDecl, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; - if (SuppressNew) + if (HasNoEffect) return TagD; } @@ -5055,13 +5074,13 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // Verify that it is okay to explicitly instantiate here. MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo(); assert(MSInfo && "Missing static data member specialization info?"); - bool SuppressNew = false; + bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; - if (SuppressNew) + if (HasNoEffect) return DeclPtrTy(); // Instantiate static data member. @@ -5158,17 +5177,17 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, PrevDecl = Specialization; if (PrevDecl) { - bool SuppressNew = false; + bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, PrevDecl, PrevDecl->getTemplateSpecializationKind(), PrevDecl->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; // FIXME: We may still want to build some representation of this // explicit specialization. - if (SuppressNew) + if (HasNoEffect) return DeclPtrTy(); } |