"constructor declared with ellipsis here">;
def err_using_decl_can_not_refer_to_class_member : Error<
"using declaration cannot refer to class member">;
+def note_using_decl_class_member_workaround : Note<
+ "use %select{an alias declaration|a typedef declaration|a reference}0 "
+ "instead">;
def err_using_decl_can_not_refer_to_namespace : Error<
"using declaration cannot refer to namespace">;
def err_using_decl_constructor : Error<
const LookupResult &Previous);
bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc);
NamedDecl *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);
/// 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);
// 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;
}
}
if (!NewUD->isInvalidDecl() &&
- SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS,
+ SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), SS, NameInfo,
D->getLocation()))
NewUD->setInvalidDecl();
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: not %clang_cc1 -fsyntax-only -std=c++98 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --check-prefix=CXX98 %s
+// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck --check-prefix=CXX11 %s
// C++0x N2914.
struct X {
using X::i; // expected-error{{using declaration cannot refer to class member}}
using X::s; // expected-error{{using declaration cannot refer to class member}}
}
+
+struct S {
+ static int n;
+ struct Q {};
+ enum E {};
+ typedef Q T;
+ void f();
+ static void g();
+};
+
+using S::n; // expected-error{{class member}} expected-note {{use a reference instead}}
+#if __cplusplus < 201103L
+// CXX98-NOT: fix-it:"{{.*}}":{[[@LINE-2]]
+#else
+// CXX11: fix-it:"{{.*}}":{[[@LINE-4]]:1-[[@LINE-4]]:6}:"auto &n = "
+#endif
+
+using S::Q; // expected-error{{class member}}
+#if __cplusplus < 201103L
+// expected-note@-2 {{use a typedef declaration instead}}
+// CXX98: fix-it:"{{.*}}":{[[@LINE-3]]:1-[[@LINE-3]]:6}:"typedef"
+// CXX98: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:11}:" Q"
+#else
+// expected-note@-6 {{use an alias declaration instead}}
+// CXX11: fix-it:"{{.*}}":{[[@LINE-7]]:7-[[@LINE-7]]:7}:"Q = "
+#endif
+
+using S::E; // expected-error{{class member}}
+#if __cplusplus < 201103L
+// expected-note@-2 {{use a typedef declaration instead}}
+// CXX98: fix-it:"{{.*}}":{[[@LINE-3]]:1-[[@LINE-3]]:6}:"typedef"
+// CXX98: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:11}:" E"
+#else
+// expected-note@-6 {{use an alias declaration instead}}
+// CXX11: fix-it:"{{.*}}":{[[@LINE-7]]:7-[[@LINE-7]]:7}:"E = "
+#endif
+
+using S::T; // expected-error{{class member}}
+#if __cplusplus < 201103L
+// expected-note@-2 {{use a typedef declaration instead}}
+// CXX98: fix-it:"{{.*}}":{[[@LINE-3]]:1-[[@LINE-3]]:6}:"typedef"
+// CXX98: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:11}:" T"
+#else
+// expected-note@-6 {{use an alias declaration instead}}
+// CXX11: fix-it:"{{.*}}":{[[@LINE-7]]:7-[[@LINE-7]]:7}:"T = "
+#endif
+
+using S::f; // expected-error{{class member}}
+using S::g; // expected-error{{class member}}
+
+void h() {
+ using S::n; // expected-error{{class member}} expected-note {{use a reference instead}}
+#if __cplusplus < 201103L
+ // CXX98-NOT: fix-it:"{{.*}}":{[[@LINE-2]]
+#else
+ // CXX11: fix-it:"{{.*}}":{[[@LINE-4]]:3-[[@LINE-4]]:8}:"auto &n = "
+#endif
+
+ using S::Q; // expected-error{{class member}}
+#if __cplusplus < 201103L
+ // expected-note@-2 {{use a typedef declaration instead}}
+ // CXX98: fix-it:"{{.*}}":{[[@LINE-3]]:3-[[@LINE-3]]:8}:"typedef"
+ // CXX98: fix-it:"{{.*}}":{[[@LINE-4]]:13-[[@LINE-4]]:13}:" Q"
+#else
+ // expected-note@-6 {{use an alias declaration instead}}
+ // CXX11: fix-it:"{{.*}}":{[[@LINE-7]]:9-[[@LINE-7]]:9}:"Q = "
+#endif
+
+ using S::E; // expected-error{{class member}}
+#if __cplusplus < 201103L
+ // expected-note@-2 {{use a typedef declaration instead}}
+ // CXX98: fix-it:"{{.*}}":{[[@LINE-3]]:3-[[@LINE-3]]:8}:"typedef"
+ // CXX98: fix-it:"{{.*}}":{[[@LINE-4]]:13-[[@LINE-4]]:13}:" E"
+#else
+ // expected-note@-6 {{use an alias declaration instead}}
+ // CXX11: fix-it:"{{.*}}":{[[@LINE-7]]:9-[[@LINE-7]]:9}:"E = "
+#endif
+
+ using S::T; // expected-error{{class member}}
+#if __cplusplus < 201103L
+ // expected-note@-2 {{use a typedef declaration instead}}
+ // CXX98: fix-it:"{{.*}}":{[[@LINE-3]]:3-[[@LINE-3]]:8}:"typedef"
+ // CXX98: fix-it:"{{.*}}":{[[@LINE-4]]:13-[[@LINE-4]]:13}:" T"
+#else
+ // expected-note@-6 {{use an alias declaration instead}}
+ // CXX11: fix-it:"{{.*}}":{[[@LINE-7]]:9-[[@LINE-7]]:9}:"T = "
+#endif
+
+ using S::f; // expected-error{{class member}}
+ using S::g; // expected-error{{class member}}
+}