diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 |
2 files changed, 51 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index dac2490c643..850db26e9af 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7393,7 +7393,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return 0; // Check for bad qualifiers. - if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc)) + if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc)) return 0; DeclContext *LookupContext = computeDeclContext(SS); @@ -7619,6 +7619,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, /// scope. If an error is found, diagnoses it and returns true. bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, SourceLocation NameLoc) { DeclContext *NamedContext = computeDeclContext(SS); @@ -7630,8 +7631,56 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // If we weren't able to compute a valid scope, it must be a // dependent class scope. if (!NamedContext || NamedContext->isRecord()) { + auto *RD = dyn_cast<CXXRecordDecl>(NamedContext); + if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD)) + RD = 0; + Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member) << SS.getRange(); + + // If we have a complete, non-dependent source type, try to suggest a + // way to get the same effect. + if (!RD) + return true; + + // Find what this using-declaration was referring to. + LookupResult R(*this, NameInfo, LookupOrdinaryName); + R.setHideTags(false); + R.suppressDiagnostics(); + LookupQualifiedName(R, RD); + + if (R.getAsSingle<TypeDecl>()) { + if (getLangOpts().CPlusPlus11) { + // Convert 'using X::Y;' to 'using Y = X::Y;'. + Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround) + << 0 // alias declaration + << FixItHint::CreateInsertion(SS.getBeginLoc(), + NameInfo.getName().getAsString() + + " = "); + } else { + // Convert 'using X::Y;' to 'typedef X::Y Y;'. + SourceLocation InsertLoc = + PP.getLocForEndOfToken(NameInfo.getLocEnd()); + Diag(InsertLoc, diag::note_using_decl_class_member_workaround) + << 1 // typedef declaration + << FixItHint::CreateReplacement(UsingLoc, "typedef") + << FixItHint::CreateInsertion( + InsertLoc, " " + NameInfo.getName().getAsString()); + } + } else if (R.getAsSingle<VarDecl>()) { + // Don't provide a fixit outside C++11 mode; we don't want to suggest + // repeating the type of the static data member here. + FixItHint FixIt; + if (getLangOpts().CPlusPlus11) { + // Convert 'using X::Y;' to 'auto &Y = X::Y;'. + FixIt = FixItHint::CreateReplacement( + UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = "); + } + + Diag(UsingLoc, diag::note_using_decl_class_member_workaround) + << 2 // reference declaration + << FixIt; + } return true; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8766c887f8b..316b574fdfa 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2169,7 +2169,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { } if (!NewUD->isInvalidDecl() && - SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, + SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, NameInfo, D->getLocation())) NewUD->setInvalidDecl(); |