[PATCH] ms-compat: Fix taking the address of a member of a dependent base
Reid Kleckner
rnk at google.com
Mon Oct 14 14:41:43 PDT 2013
- Explicitly assume that unresolved unqualified id exprs are members of dependent bases.
Hi rsmith,
http://llvm-reviews.chandlerc.com/D1892
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1892?vs=4823&id=4901#toc
Files:
lib/AST/ExprCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/TreeTransform.h
test/SemaTemplate/ms-lookup-template-base-classes.cpp
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp
+++ lib/AST/ExprCXX.cpp
@@ -456,6 +456,7 @@
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
+ assert(QualifierLoc && "should be created for dependent qualifiers");
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args)
size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size());
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -2020,14 +2020,26 @@
if (R.empty()) {
// In Microsoft mode, if we are inside a template class member function
// whose parent class has dependent base classes, and we can't resolve
- // an identifier, then assume the identifier is type dependent. The
- // goal is to postpone name lookup to instantiation time to be able to
- // search into the type dependent base classes.
+ // an identifier, then assume the identifier is a member of a dependent
+ // base class. The goal is to postpone name lookup to instantiation time
+ // to be able to search into the type dependent base classes.
+ // FIXME: If we want 100% compatibility with MSVC, we will have delay all
+ // unqualified name lookup. Any name lookup during template parsing means
+ // clang might find something that MSVC doesn't. For now, we only handle
+ // the common case of members of a dependent base class.
if (getLangOpts().MicrosoftMode) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
- if (MD && MD->getParent()->hasAnyDependentBases())
- return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
- IsAddressOfOperand, TemplateArgs);
+ if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) {
+ assert(SS.isEmpty() && "qualifiers should be already handled");
+ QualType ThisType = MD->getThisType(Context);
+ // Since the 'this' expression is synthesized, we don't need to
+ // perform the double-lookup check.
+ NamedDecl *FirstQualifierInScope = 0;
+ return Owned(CXXDependentScopeMemberExpr::Create(
+ Context, /*This=*/0, ThisType, /*IsArrow=*/true,
+ /*Op=*/SourceLocation(), SS.getWithLocInContext(Context),
+ TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs));
+ }
}
// Don't diagnose an empty lookup for inline assmebly.
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -8127,6 +8127,7 @@
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E,
bool IsAddressOfOperand) {
+ assert(E->getQualifierLoc());
NestedNameSpecifierLoc QualifierLoc
= getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
if (!QualifierLoc)
Index: test/SemaTemplate/ms-lookup-template-base-classes.cpp
===================================================================
--- test/SemaTemplate/ms-lookup-template-base-classes.cpp
+++ test/SemaTemplate/ms-lookup-template-base-classes.cpp
@@ -196,3 +196,43 @@
}
} // namespace PR12701
+
+namespace PR16014 {
+
+struct A {
+ int a;
+ static int sa;
+};
+template <typename T> struct B : T {
+ int foo() { return a; }
+ int *bar() { return &a; }
+ int baz() { return T::a; }
+ int T::*qux() { return &T::a; }
+ static int T::*stuff() { return &T::a; }
+ static int stuff1() { return T::sa; }
+ static int *stuff2() { return &T::sa; }
+};
+
+template <typename T> struct C : T {
+ int foo() { return b; } // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}}
+ int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}}
+ 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'}}
+};
+
+template struct B<A>;
+template struct C<A>; // expected-note-re 1+ {{in instantiation of member function 'PR16014::C<PR16014::A>::.*' requested here}}
+
+template <typename T> struct D : T {
+ struct Inner {
+ int foo() {
+ // FIXME: MSVC can find this in D's base T! Even worse, if ::sa exists,
+ // clang will use it instead.
+ return sa; // expected-error {{use of undeclared identifier 'sa'}}
+ }
+ };
+};
+template struct D<A>;
+
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1892.2.patch
Type: text/x-patch
Size: 4976 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131014/e88e3699/attachment.bin>
More information about the cfe-commits
mailing list