mattd created this revision. Fixes: PR28290
When checking an argument list, arguments from the templated class instance, were returning 'is dependent' based on the 'this' pointer. In that case, arguments were being marked dependent, and name lookup was delayed until template instantiation. This had the side-effect of -fdelayed-template-parsing in certain cases (attached test case), when that should not have been the case, especially since that flag was never passed. According to the standard the referenced member's type needs to be checked: [temp.dep.expr]p5: A class member access expression (5.2.5) is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization. This change decides if the argument belongs to a MemberExpr. If so, then the type of the expression is checked if it is dependent or not. https://reviews.llvm.org/D40566 Files: lib/AST/Expr.cpp test/CXX/class.access/class.access.dcl/p1.cpp test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp test/SemaTemplate/template-with-invalid-decl.cpp Index: test/SemaTemplate/template-with-invalid-decl.cpp =================================================================== --- test/SemaTemplate/template-with-invalid-decl.cpp +++ test/SemaTemplate/template-with-invalid-decl.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +class UBS; + +template <bool bCS> struct FIBH +{ + FIBH() { GDN(BS); } // expected-error {{use of undeclared identifier 'GDN'}} + class UBS* BS; +}; + +extern void foo() +{ + FIBH<false> IBH; +} + +extern void GDN(UBS* BS); Index: test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp =================================================================== --- test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp +++ test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp @@ -29,7 +29,7 @@ }; } -struct Opaque0 {}; +struct Opaque0 {}; // expected-note-re 1-2{{candidate constructor {{.*}}}} namespace test1 { struct A { @@ -112,7 +112,7 @@ } void test5() { - Opaque0 _ = hiding; + Opaque0 _ = hiding; // expected-error {{no viable conversion from 'int' to 'Opaque0'}} } }; } Index: test/CXX/class.access/class.access.dcl/p1.cpp =================================================================== --- test/CXX/class.access/class.access.dcl/p1.cpp +++ test/CXX/class.access/class.access.dcl/p1.cpp @@ -56,7 +56,7 @@ }; } -struct Opaque0 {}; +struct Opaque0 {}; // expected-note-re 1-2 {{candidate constructor {{.*}}}} namespace test1 { struct A { @@ -196,7 +196,7 @@ } void test5() { - Opaque0 _ = hiding; + Opaque0 _ = hiding; // expected-error {{no viable conversion from 'int' to 'Opaque0'}} } }; } Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -2738,12 +2738,27 @@ return false; } +/// \brief Returns true if the expression is a MemberExpr +/// with a dependent type. +static bool isDependentMember(const Expr *E) +{ + if (const auto ME = dyn_cast_or_null<MemberExpr>(E)) + if (const auto Member = ME->getMemberDecl()) + return Member->getType()->isDependentType(); + + return false; +} + /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. bool Expr::hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs) { - for (unsigned I = 0; I < Exprs.size(); ++I) - if (Exprs[I]->isTypeDependent()) + for (const auto E : Exprs) { + if (isa<MemberExpr>(E)) { + if (isDependentMember(E)) + return true; + } else if (E->isTypeDependent()) return true; + } return false; }
Index: test/SemaTemplate/template-with-invalid-decl.cpp =================================================================== --- test/SemaTemplate/template-with-invalid-decl.cpp +++ test/SemaTemplate/template-with-invalid-decl.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -verify %s + +class UBS; + +template <bool bCS> struct FIBH +{ + FIBH() { GDN(BS); } // expected-error {{use of undeclared identifier 'GDN'}} + class UBS* BS; +}; + +extern void foo() +{ + FIBH<false> IBH; +} + +extern void GDN(UBS* BS); Index: test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp =================================================================== --- test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp +++ test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp @@ -29,7 +29,7 @@ }; } -struct Opaque0 {}; +struct Opaque0 {}; // expected-note-re 1-2{{candidate constructor {{.*}}}} namespace test1 { struct A { @@ -112,7 +112,7 @@ } void test5() { - Opaque0 _ = hiding; + Opaque0 _ = hiding; // expected-error {{no viable conversion from 'int' to 'Opaque0'}} } }; } Index: test/CXX/class.access/class.access.dcl/p1.cpp =================================================================== --- test/CXX/class.access/class.access.dcl/p1.cpp +++ test/CXX/class.access/class.access.dcl/p1.cpp @@ -56,7 +56,7 @@ }; } -struct Opaque0 {}; +struct Opaque0 {}; // expected-note-re 1-2 {{candidate constructor {{.*}}}} namespace test1 { struct A { @@ -196,7 +196,7 @@ } void test5() { - Opaque0 _ = hiding; + Opaque0 _ = hiding; // expected-error {{no viable conversion from 'int' to 'Opaque0'}} } }; } Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -2738,12 +2738,27 @@ return false; } +/// \brief Returns true if the expression is a MemberExpr +/// with a dependent type. +static bool isDependentMember(const Expr *E) +{ + if (const auto ME = dyn_cast_or_null<MemberExpr>(E)) + if (const auto Member = ME->getMemberDecl()) + return Member->getType()->isDependentType(); + + return false; +} + /// hasAnyTypeDependentArguments - Determines if any of the expressions /// in Exprs is type-dependent. bool Expr::hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs) { - for (unsigned I = 0; I < Exprs.size(); ++I) - if (Exprs[I]->isTypeDependent()) + for (const auto E : Exprs) { + if (isa<MemberExpr>(E)) { + if (isDependentMember(E)) + return true; + } else if (E->isTypeDependent()) return true; + } return false; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits