diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-14 23:13:10 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-14 23:13:10 +0000 |
commit | f1c66b40213784a1c4612f04c14cafa2b0e89988 (patch) | |
tree | e7ce75134aa9dfc30fce2b5a85088baf65423294 /lib/Sema/SemaCXXScopeSpec.cpp | |
parent | 59e7f4e6e69872d2fc4031f66b47b8ad64967e51 (diff) | |
download | clang-f1c66b40213784a1c4612f04c14cafa2b0e89988.tar.gz |
Instantiating a class template should not instantiate the definition of any
scoped enumeration members. Later uses of an enumeration temploid as a nested
name specifier should cause its instantiation. Plus some groundwork for
explicit specialization of member enumerations of class templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152750 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 72 |
1 files changed, 41 insertions, 31 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 1c414dda5d..5e6c27b15d 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -13,6 +13,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Template.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" @@ -209,43 +210,52 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC) { assert(DC != 0 && "given null context"); - if (TagDecl *tag = dyn_cast<TagDecl>(DC)) { - // If this is a dependent type, then we consider it complete. - if (tag->isDependentContext()) - return false; + TagDecl *tag = dyn_cast<TagDecl>(DC); - // If we're currently defining this type, then lookup into the - // type is okay: don't complain that it isn't complete yet. - QualType type = Context.getTypeDeclType(tag); - const TagType *tagType = type->getAs<TagType>(); - if (tagType && tagType->isBeingDefined()) - return false; + // If this is a dependent type, then we consider it complete. + if (!tag || tag->isDependentContext()) + return false; - SourceLocation loc = SS.getLastQualifierNameLoc(); - if (loc.isInvalid()) loc = SS.getRange().getBegin(); + // If we're currently defining this type, then lookup into the + // type is okay: don't complain that it isn't complete yet. + QualType type = Context.getTypeDeclType(tag); + const TagType *tagType = type->getAs<TagType>(); + if (tagType && tagType->isBeingDefined()) + return false; - // The type must be complete. - if (RequireCompleteType(loc, type, - PDiag(diag::err_incomplete_nested_name_spec) - << SS.getRange())) { - SS.SetInvalid(SS.getRange()); - return true; - } + SourceLocation loc = SS.getLastQualifierNameLoc(); + if (loc.isInvalid()) loc = SS.getRange().getBegin(); - // Fixed enum types are complete, but they aren't valid as scopes - // until we see a definition, so awkwardly pull out this special - // case. - if (const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType)) { - if (!enumType->getDecl()->isCompleteDefinition()) { - Diag(loc, diag::err_incomplete_nested_name_spec) - << type << SS.getRange(); - SS.SetInvalid(SS.getRange()); - return true; - } - } + // The type must be complete. + if (RequireCompleteType(loc, type, + PDiag(diag::err_incomplete_nested_name_spec) + << SS.getRange())) { + SS.SetInvalid(SS.getRange()); + return true; } - return false; + // Fixed enum types are complete, but they aren't valid as scopes + // until we see a definition, so awkwardly pull out this special + // case. + const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType); + if (!enumType || enumType->getDecl()->isCompleteDefinition()) + return false; + + // Try to instantiate the definition, if this is a specialization of an + // enumeration temploid. + EnumDecl *ED = enumType->getDecl(); + if (EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { + MemberSpecializationInfo *MSI = ED->getMemberSpecializationInfo(); + if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + return InstantiateEnum(loc, ED, Pattern, + getTemplateInstantiationArgs(ED), + TSK_ImplicitInstantiation); + } + + Diag(loc, diag::err_incomplete_nested_name_spec) + << type << SS.getRange(); + SS.SetInvalid(SS.getRange()); + return true; } bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, |