[cfe-commits] r126880 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/AST/ExprCXX.cpp test/Index/annotate-nested-name-specifier.cpp tools/libclang/CIndex.cpp

Douglas Gregor dgregor at apple.com
Wed Mar 2 13:06:53 PST 2011


Author: dgregor
Date: Wed Mar  2 15:06:53 2011
New Revision: 126880

URL: http://llvm.org/viewvc/llvm-project?rev=126880&view=rev
Log:
Fix the source range for a member access expression that includes a
nested-name-specifier and improve the detection of implicit 'this'
bases. Fixes <rdar://problem/8750392>.

Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/test/Index/annotate-nested-name-specifier.cpp
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=126880&r1=126879&r2=126880&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Mar  2 15:06:53 2011
@@ -536,6 +536,9 @@
   /// temporary object of the given class type.
   bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const;
 
+  /// \brief Whether this expression is an implicit reference to 'this' in C++.
+  bool isImplicitCXXThis() const;
+  
   const Expr *IgnoreParens() const {
     return const_cast<Expr*>(this)->IgnoreParens();
   }
@@ -2070,21 +2073,15 @@
   SourceLocation getMemberLoc() const { return MemberLoc; }
   void setMemberLoc(SourceLocation L) { MemberLoc = L; }
 
-  SourceRange getSourceRange() const {
-    // If we have an implicit base (like a C++ implicit this),
-    // make sure not to return its location
-    // FIXME: This isn't the way to do the above.
-    SourceLocation EndLoc = (HasExplicitTemplateArgumentList)
-      ? getRAngleLoc() : getMemberNameInfo().getEndLoc();
-
-    SourceLocation BaseLoc = getBase()->getLocStart();
-    if (BaseLoc.isInvalid())
-      return SourceRange(MemberLoc, EndLoc);
-    return SourceRange(BaseLoc, EndLoc);
-  }
-
+  SourceRange getSourceRange() const;
+  
   SourceLocation getExprLoc() const { return MemberLoc; }
 
+  /// \brief Determine whether the base of this explicit is implicit.
+  bool isImplicitAccess() const {
+    return getBase() && getBase()->isImplicitCXXThis();
+  }
+  
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == MemberExprClass;
   }

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=126880&r1=126879&r2=126880&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Mar  2 15:06:53 2011
@@ -943,6 +943,28 @@
   return E;
 }
 
+SourceRange MemberExpr::getSourceRange() const {
+  SourceLocation StartLoc;
+  if (isImplicitAccess()) {
+    if (hasQualifier())
+      StartLoc = getQualifierLoc().getBeginLoc();
+    else
+      StartLoc = MemberLoc;
+  } else {
+    // FIXME: We don't want this to happen. Rather, we should be able to
+    // detect all kinds of implicit accesses more cleanly.
+    StartLoc = getBase()->getLocStart();
+    if (StartLoc.isInvalid())
+      StartLoc = MemberLoc;
+  }
+  
+  SourceLocation EndLoc = 
+    HasExplicitTemplateArgumentList? getRAngleLoc() 
+                                   : getMemberNameInfo().getEndLoc();
+  
+  return SourceRange(StartLoc, EndLoc);
+}
+
 const char *CastExpr::getCastKindName() const {
   switch (getCastKind()) {
   case CK_Dependent:
@@ -2017,6 +2039,42 @@
   return true;
 }
 
+bool Expr::isImplicitCXXThis() const {
+  const Expr *E = this;
+  
+  // Strip away parentheses and casts we don't care about.
+  while (true) {
+    if (const ParenExpr *Paren = dyn_cast<ParenExpr>(E)) {
+      E = Paren->getSubExpr();
+      continue;
+    }
+    
+    if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+      if (ICE->getCastKind() == CK_NoOp ||
+          ICE->getCastKind() == CK_LValueToRValue ||
+          ICE->getCastKind() == CK_DerivedToBase || 
+          ICE->getCastKind() == CK_UncheckedDerivedToBase) {
+        E = ICE->getSubExpr();
+        continue;
+      }
+    }
+    
+    if (const UnaryOperator* UnOp = dyn_cast<UnaryOperator>(E)) {
+      if (UnOp->getOpcode() == UO_Extension) {
+        E = UnOp->getSubExpr();
+        continue;
+      }
+    }
+    
+    break;
+  }
+  
+  if (const CXXThisExpr *This = dyn_cast<CXXThisExpr>(E))
+    return This->isImplicit();
+  
+  return false;
+}
+
 /// hasAnyTypeDependentArguments - Determines if any of the expressions
 /// in Exprs is type-dependent.
 bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=126880&r1=126879&r2=126880&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Mar  2 15:06:53 2011
@@ -783,46 +783,11 @@
   return E;
 }
 
-/// \brief Determine whether this expression is an implicit C++ 'this'.
-static bool isImplicitThis(const Expr *E) {
-  // Strip away parentheses and casts we don't care about.
-  while (true) {
-    if (const ParenExpr *Paren = dyn_cast<ParenExpr>(E)) {
-      E = Paren->getSubExpr();
-      continue;
-    }
-    
-    if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-      if (ICE->getCastKind() == CK_NoOp ||
-          ICE->getCastKind() == CK_LValueToRValue ||
-          ICE->getCastKind() == CK_DerivedToBase || 
-          ICE->getCastKind() == CK_UncheckedDerivedToBase) {
-        E = ICE->getSubExpr();
-        continue;
-      }
-    }
-    
-    if (const UnaryOperator* UnOp = dyn_cast<UnaryOperator>(E)) {
-      if (UnOp->getOpcode() == UO_Extension) {
-        E = UnOp->getSubExpr();
-        continue;
-      }
-    }
-    
-    break;
-  }
-  
-  if (const CXXThisExpr *This = dyn_cast<CXXThisExpr>(E))
-    return This->isImplicit();
-  
-  return false;
-}
-
 bool CXXDependentScopeMemberExpr::isImplicitAccess() const {
   if (Base == 0)
     return true;
   
-  return isImplicitThis(cast<Expr>(Base));
+  return cast<Expr>(Base)->isImplicitCXXThis();
 }
 
 UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, 
@@ -851,7 +816,7 @@
   if (Base == 0)
     return true;
   
-  return isImplicitThis(cast<Expr>(Base));
+  return cast<Expr>(Base)->isImplicitCXXThis();
 }
 
 UnresolvedMemberExpr *

Modified: cfe/trunk/test/Index/annotate-nested-name-specifier.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-nested-name-specifier.cpp?rev=126880&r1=126879&r2=126880&view=diff
==============================================================================
--- cfe/trunk/test/Index/annotate-nested-name-specifier.cpp (original)
+++ cfe/trunk/test/Index/annotate-nested-name-specifier.cpp Wed Mar  2 15:06:53 2011
@@ -126,7 +126,18 @@
   typedef outer_alias::inner::apply_meta<T_type, U_type::template apply> type;
 };
 
-// RUN: c-index-test -test-annotate-tokens=%s:13:1:128:1 %s | FileCheck %s
+struct X8 {
+  void f();
+};
+
+struct X9 : X8 {
+  typedef X8 inherited;
+  void f() { 
+    inherited::f();
+  }
+};
+
+// RUN: c-index-test -test-annotate-tokens=%s:13:1:137:1 %s | FileCheck %s
 
 // CHECK: Keyword: "using" [14:1 - 14:6] UsingDeclaration=vector[4:12]
 // CHECK: Identifier: "outer_alias" [14:7 - 14:18] NamespaceRef=outer_alias:10:11
@@ -449,3 +460,7 @@
 // CHECK: Punctuation: ">" [126:72 - 126:73] TypedefDecl=type:126:74 (Definition)
 // CHECK: Identifier: "type" [126:74 - 126:78] TypedefDecl=type:126:74 (Definition)
 
+// Member access expressions
+// CHECK: Identifier: "inherited" [136:5 - 136:14] TypeRef=inherited:134:14
+// CHECK: Punctuation: "::" [136:14 - 136:16] MemberRefExpr=f:130:8
+// CHECK: Identifier: "f" [136:16 - 136:17] MemberRefExpr=f:130:8

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=126880&r1=126879&r2=126880&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Wed Mar  2 15:06:53 2011
@@ -1979,12 +1979,8 @@
   // visit it.
   // FIXME: If we ever want to show these implicit accesses, this will be
   // unfortunate. However, clang_getCursor() relies on this behavior.
-  if (CXXThisExpr *This
-            = llvm::dyn_cast<CXXThisExpr>(M->getBase()->IgnoreParenImpCasts()))
-    if (This->isImplicit())
-      return;
-  
-  AddStmt(M->getBase());
+  if (!M->isImplicitAccess())
+    AddStmt(M->getBase());
 }
 void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
   AddTypeLoc(E->getEncodedTypeSourceInfo());





More information about the cfe-commits mailing list