summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaCXXScopeSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp35
1 files changed, 32 insertions, 3 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index f7aace625a92..ab0e709a97e7 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -117,8 +117,18 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
// specializations, we're entering into the definition of that
// class template partial specialization.
if (ClassTemplatePartialSpecializationDecl *PartialSpec
- = ClassTemplate->findPartialSpecialization(ContextType))
+ = ClassTemplate->findPartialSpecialization(ContextType)) {
+ // A declaration of the partial specialization must be visible.
+ // We can always recover here, because this only happens when we're
+ // entering the context, and that can't happen in a SFINAE context.
+ assert(!isSFINAEContext() &&
+ "partial specialization scope specifier in SFINAE context?");
+ if (!hasVisibleDeclaration(PartialSpec))
+ diagnoseMissingImport(SS.getLastQualifierNameLoc(), PartialSpec,
+ MissingImportKind::PartialSpecialization,
+ /*Recover*/true);
return PartialSpec;
+ }
}
} else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) {
// The nested name specifier refers to a member of a class template.
@@ -195,6 +205,8 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
TagDecl *tag = dyn_cast<TagDecl>(DC);
// If this is a dependent type, then we consider it complete.
+ // FIXME: This is wrong; we should require a (visible) definition to
+ // exist in this case too.
if (!tag || tag->isDependentContext())
return false;
@@ -218,10 +230,23 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
// Fixed enum types are complete, but they aren't valid as scopes
// until we see a definition, so awkwardly pull out this special
// case.
- // FIXME: The definition might not be visible; complain if it is not.
const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType);
- if (!enumType || enumType->getDecl()->isCompleteDefinition())
+ if (!enumType)
return false;
+ if (enumType->getDecl()->isCompleteDefinition()) {
+ // If we know about the definition but it is not visible, complain.
+ NamedDecl *SuggestedDef = nullptr;
+ if (!hasVisibleDefinition(enumType->getDecl(), &SuggestedDef,
+ /*OnlyNeedComplete*/false)) {
+ // If the user is going to see an error here, recover by making the
+ // definition visible.
+ bool TreatAsComplete = !isSFINAEContext();
+ diagnoseMissingImport(loc, SuggestedDef, MissingImportKind::Definition,
+ /*Recover*/TreatAsComplete);
+ return !TreatAsComplete;
+ }
+ return false;
+ }
// Try to instantiate the definition, if this is a specialization of an
// enumeration temploid.
@@ -606,6 +631,10 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest)
<< Name);
+ if (Corrected.getCorrectionSpecifier())
+ SS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
+ SourceRange(Found.getNameLoc()));
+
if (NamedDecl *ND = Corrected.getFoundDecl())
Found.addDecl(ND);
Found.setLookupName(Corrected.getCorrection());