]> granicus.if.org Git - clang/commitdiff
Don't repeat lookup when instantiating resolved member expressions.
authorJohn McCall <rjmccall@apple.com>
Fri, 15 Jan 2010 08:34:02 +0000 (08:34 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 15 Jan 2010 08:34:02 +0000 (08:34 +0000)
Adjust BuildMemberReferenceExpr to perform the inheritance check on implicit
member accesses, which can arise from unqualified lookups and therefore may
reference decls from enclosing class scopes.

Fixes PR 5838.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93510 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/TreeTransform.h
test/SemaTemplate/instantiate-member-expr.cpp

index 953a00fa42298627c06c71a55ec04e4dae62b704..fab729299936578afa2d4a9742fe5dcacefa801b 100644 (file)
@@ -1596,13 +1596,13 @@ public:
                                             QualType BaseType,
                                             SourceLocation OpLoc, bool IsArrow,
                                             const CXXScopeSpec &SS,
+                                            NamedDecl *FirstQualifierInScope,
                                             LookupResult &R,
                                  const TemplateArgumentListInfo *TemplateArgs);
 
   OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
                                     bool &IsArrow, SourceLocation OpLoc,
                                     const CXXScopeSpec &SS,
-                                    NamedDecl *FirstQualifierInScope,
                                     DeclPtrTy ObjCImpDecl);
 
   bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
index e02dbd6bebdd4a5f81dd3546aab8f00b549b9187..034accd1c4e10fd86ba40dff2f82cee4fc79b491 100644 (file)
@@ -1397,7 +1397,9 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
   return BuildMemberReferenceExpr(ExprArg(*this, This), ThisType,
                                   /*OpLoc*/ SourceLocation(),
                                   /*IsArrow*/ true,
-                                  SS, R, TemplateArgs);
+                                  SS,
+                                  /*FirstQualifierInScope*/ 0,
+                                  R, TemplateArgs);
 }
 
 bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
@@ -2471,8 +2473,7 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
   } else {
     OwningExprResult Result =
       LookupMemberExpr(R, Base, IsArrow, OpLoc,
-                       SS, FirstQualifierInScope,
-                       /*ObjCImpDecl*/ DeclPtrTy());
+                       SS, /*ObjCImpDecl*/ DeclPtrTy());
 
     if (Result.isInvalid()) {
       Owned(Base);
@@ -2484,13 +2485,15 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
   }
 
   return BuildMemberReferenceExpr(ExprArg(*this, Base), BaseType,
-                                  OpLoc, IsArrow, SS, R, TemplateArgs);
+                                  OpLoc, IsArrow, SS, FirstQualifierInScope,
+                                  R, TemplateArgs);
 }
 
 Sema::OwningExprResult
 Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
                                SourceLocation OpLoc, bool IsArrow,
                                const CXXScopeSpec &SS,
+                               NamedDecl *FirstQualifierInScope,
                                LookupResult &R,
                          const TemplateArgumentListInfo *TemplateArgs) {
   Expr *BaseExpr = Base.takeAs<Expr>();
@@ -2520,11 +2523,17 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
     return ExprError();
   }
 
-  // Diagnose qualified lookups that find only declarations from a
-  // non-base type.  Note that it's okay for lookup to find
-  // declarations from a non-base type as long as those aren't the
-  // ones picked by overload resolution.
-  if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
+  // Diagnose lookups that find only declarations from a non-base
+  // type.  This is possible for either qualified lookups (which may
+  // have been qualified with an unrelated type) or implicit member
+  // expressions (which were found with unqualified lookup and thus
+  // may have come from an enclosing scope).  Note that it's okay for
+  // lookup to find declarations from a non-base type as long as those
+  // aren't the ones picked by overload resolution.
+  if ((SS.isSet() || !BaseExpr ||
+       (isa<CXXThisExpr>(BaseExpr) &&
+        cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
+      CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
     return ExprError();
 
   // Construct an unresolved result if we in fact got an unresolved
@@ -2666,7 +2675,6 @@ Sema::OwningExprResult
 Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
                        bool &IsArrow, SourceLocation OpLoc,
                        const CXXScopeSpec &SS,
-                       NamedDecl *FirstQualifierInScope,
                        DeclPtrTy ObjCImpDecl) {
   assert(BaseExpr && "no base expression");
 
@@ -3101,7 +3109,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
         << Property->getDeclName();          
 
       return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS,
-                              FirstQualifierInScope, ObjCImpDecl);
+                              ObjCImpDecl);
     }
 
     return ExprError(Diag(MemberLoc, diag::err_property_not_found)
@@ -3204,8 +3212,7 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
       DecomposeTemplateName(R, Id);
     } else {
       Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
-                                SS, FirstQualifierInScope,
-                                ObjCImpDecl);
+                                SS, ObjCImpDecl);
 
       if (Result.isInvalid()) {
         Owned(Base);
@@ -3226,7 +3233,8 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
     }
 
     Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(),
-                                      OpLoc, IsArrow, SS, R, TemplateArgs);
+                                      OpLoc, IsArrow, SS, FirstQualifierInScope,
+                                      R, TemplateArgs);
   }
 
   return move(Result);
index 419dd9c00f96ef912699ec377aad3d5678af4e28..445ef0dac7976c6af67495e66d17356d78a56c22 100644 (file)
@@ -975,12 +975,15 @@ public:
 
     QualType BaseType = ((Expr*) Base.get())->getType();
 
-    // FIXME: wait, this is re-performing lookup?
+    LookupResult R(getSema(), Member->getDeclName(), MemberLoc,
+                   Sema::LookupMemberName);
+    R.addDecl(Member);
+    R.resolveKind();
+
     return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
                                               OpLoc, isArrow,
                                               SS, FirstQualifierInScope,
-                                              Member->getDeclName(), MemberLoc,
-                                              ExplicitTemplateArgs);
+                                              R, ExplicitTemplateArgs);
   }
 
   /// \brief Build a new binary operator expression.
@@ -1561,6 +1564,7 @@ public:
                                                bool IsArrow,
                                                NestedNameSpecifier *Qualifier,
                                                SourceRange QualifierRange,
+                                               NamedDecl *FirstQualifierInScope,
                                                LookupResult &R,
                                 const TemplateArgumentListInfo *TemplateArgs) {
     CXXScopeSpec SS;
@@ -1569,7 +1573,8 @@ public:
 
     return SemaRef.BuildMemberReferenceExpr(move(BaseE), BaseType,
                                             OperatorLoc, IsArrow,
-                                            SS, R, TemplateArgs);
+                                            SS, FirstQualifierInScope,
+                                            R, TemplateArgs);
   }
 
   /// \brief Build a new Objective-C @encode expression.
@@ -3713,6 +3718,12 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
   SourceLocation FakeOperatorLoc
     = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
 
+  // FIXME: to do this check properly, we will need to preserve the
+  // first-qualifier-in-scope here, just in case we had a dependent
+  // base (and therefore couldn't do the check) and a
+  // nested-name-qualifier (and therefore could do the lookup).
+  NamedDecl *FirstQualifierInScope = 0;
+
   return getDerived().RebuildMemberExpr(move(Base), FakeOperatorLoc,
                                         E->isArrow(),
                                         Qualifier,
@@ -3721,7 +3732,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
                                         Member,
                                         (E->hasExplicitTemplateArgumentList()
                                            ? &TransArgs : 0),
-                                        0);
+                                        FirstQualifierInScope);
 }
 
 template<typename Derived>
@@ -5029,6 +5040,12 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
       TransArgs.addArgument(Loc);
     }
   }
+
+  // FIXME: to do this check properly, we will need to preserve the
+  // first-qualifier-in-scope here, just in case we had a dependent
+  // base (and therefore couldn't do the check) and a
+  // nested-name-qualifier (and therefore could do the lookup).
+  NamedDecl *FirstQualifierInScope = 0;
   
   return getDerived().RebuildUnresolvedMemberExpr(move(Base),
                                                   BaseType,
@@ -5036,6 +5053,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
                                                   Old->isArrow(),
                                                   Qualifier,
                                                   Old->getQualifierRange(),
+                                                  FirstQualifierInScope,
                                                   R,
                                               (Old->hasExplicitTemplateArgs()
                                                   ? &TransArgs : 0));
index db13624d44267d0145f1d4badc2f709d808da494..324363ce96dca888d295a276b13f195b9ed21d24 100644 (file)
@@ -25,3 +25,27 @@ class RetainReleaseChecker { };
 void f(GRExprEngine& Eng) {
    Eng.registerCheck(new RetainReleaseChecker); // expected-note {{in instantiation of function template specialization 'GRExprEngine::registerCheck<class RetainReleaseChecker>' requested here}}
 }
+
+// PR 5838
+namespace test1 {
+  template<typename T> struct A {
+    int a;
+  };
+
+  template<typename T> struct B : A<float>, A<T> {
+    void f() {
+      a = 0; // should not be ambiguous
+    }
+  };
+  template struct B<int>;
+
+  struct O {
+    int a;
+    template<typename T> struct B : A<T> {
+      void f() {
+        a = 0; // expected-error {{type 'struct test1::O' is not a direct or virtual base of ''B<int>''}}
+      }
+    };
+  };
+  template struct O::B<int>; // expected-note {{in instantiation}}
+}