Author: rnk Date: Thu Aug 14 18:34:52 2014 New Revision: 215683 URL: http://llvm.org/viewvc/llvm-project?rev=215683&view=rev Log: Limit our MSVC compat hack for nested names from dependent bases
Previously, any undeclared unqualified id starting a nested name specifier in a dependent context would have its lookup retried during template instantiation. Now we limit that retry hack to methods of a class with dependent bases. Free function templates in particular are no longer affected by this hack. Also, diagnose this as a Microsoft extension. This has the downside that template authors may see this warning *and* an error during instantiation time about this identifier. Fixing that will probably require formalizing some kind of "delayed" identifier, instead of our ad-hoc solutions of forming dependent AST nodes when lookup fails. Based on a patch by Kim Gräsman! Differential Revision: http://reviews.llvm.org/D4854 Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp cfe/trunk/test/SemaTemplate/lookup-dependent-bases.cpp cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=215683&r1=215682&r2=215683&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original) +++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Thu Aug 14 18:34:52 2014 @@ -703,8 +703,13 @@ bool Sema::BuildCXXNestedNameSpecifier(S if (getLangOpts().MSVCCompat) { DeclContext *DC = LookupCtx ? LookupCtx : CurContext; if (DC->isDependentContext() && DC->isFunctionOrMethod()) { - SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); - return false; + CXXRecordDecl *ContainingClass = dyn_cast<CXXRecordDecl>(DC->getParent()); + if (ContainingClass && ContainingClass->hasAnyDependentBases()) { + Diag(IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) + << &Identifier << ContainingClass; + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; + } } } Modified: cfe/trunk/test/SemaTemplate/lookup-dependent-bases.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/lookup-dependent-bases.cpp?rev=215683&r1=215682&r2=215683&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/lookup-dependent-bases.cpp (original) +++ cfe/trunk/test/SemaTemplate/lookup-dependent-bases.cpp Thu Aug 14 18:34:52 2014 @@ -1,20 +1,55 @@ // RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s -// expected-no-diagnostics -class C { -public: - static void foo2() { } -}; -template <class T> -class A { -public: - typedef C D; -}; - -template <class T> -class B : public A<T> { -public: - void foo() { - D::foo2(); - } +namespace basic { +struct C { + static void foo2() {} }; +template <typename T> +struct A { + typedef C D; +}; + +template <typename T> +struct B : A<T> { + void foo() { + D::foo2(); // expected-warning {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}} + } +}; + +template struct B<int>; // Instantiation has no warnings. +} + +namespace nested_nodep_base { +// There are limits to our hacks, MSVC accepts this, but we don't. +struct A { + struct D { static void foo2(); }; +}; +template <typename T> +struct B : T { + struct C { + void foo() { + D::foo2(); // expected-error {{use of undeclared identifier 'D'}} + } + }; +}; + +template struct B<A>; // Instantiation has no warnings. +} + +namespace nested_dep_base { +// We actually accept this because the inner class has a dependent base even +// though it isn't a template. +struct A { + struct D { static void foo2(); }; +}; +template <typename T> +struct B { + struct C : T { + void foo() { + D::foo2(); // expected-warning {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'C' is a Microsoft extension}} + } + }; +}; + +template struct B<A>; // Instantiation has no warnings. +} Modified: cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp?rev=215683&r1=215682&r2=215683&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp (original) +++ cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp Thu Aug 14 18:34:52 2014 @@ -220,7 +220,8 @@ template <typename T> struct C : T { int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}} expected-warning {{lookup into dependent bases}} int baz() { return T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} int T::*qux() { return &T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} - int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} + int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} \ + // expected-warning {{unqualified lookup into dependent bases of class template 'C'}} }; template struct B<A>; @@ -249,7 +250,8 @@ struct A : T { ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}} } void baz() { - B::qux(); // expected-error {{use of undeclared identifier 'B'}} + B::qux(); // expected-error {{use of undeclared identifier 'B'}} \ + // expected-warning {{unqualified lookup into dependent bases of class template 'A'}} } }; @@ -460,3 +462,11 @@ template <typename T> struct D : C<T> { int x = f<NameFromBase>(); }; } + +namespace function_template_undef_impl { +template<class T> +void f() { + Undef::staticMethod(); // expected-error {{use of undeclared identifier 'Undef'}} + UndefVar.method(); // expected-error {{use of undeclared identifier 'UndefVar'}} +} +} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
